Finish adding sound effects (#2)
This commit is contained in:
parent
966951db60
commit
7fe7311371
|
@ -27,7 +27,7 @@ from sys import modules
|
|||
import pygame
|
||||
|
||||
from .constants import *
|
||||
from .utils import sign, cosin, randsign, regpoly, fill_aapolygon, choices
|
||||
from .misc import sign, cosin, randsign, regpoly, fill_aapolygon, choices, play
|
||||
from .weapons import Bullet
|
||||
|
||||
|
||||
|
@ -61,12 +61,10 @@ class Hero:
|
|||
self.spin_speed = fps / HERO_HP
|
||||
self.spin_queue = self.wound = 0.0
|
||||
|
||||
self.sfx_shot = pygame.mixer.Sound(SFX_SHOT_HERO)
|
||||
|
||||
def update(self, fps):
|
||||
"""Update the hero."""
|
||||
if self.dead:
|
||||
self.spin_queue = 0
|
||||
self.spin_queue = 0.0
|
||||
return
|
||||
old_speed, time = self.spin_speed, pygame.time.get_ticks()
|
||||
self.spin_speed = fps / (HERO_HP-self.wound**0.5)
|
||||
|
@ -111,6 +109,7 @@ class Enemy:
|
|||
spin_speed (float): speed of spinning (in frames per slash)
|
||||
spin_queue (float): frames left to finish spinning
|
||||
wound (float): amount of wound
|
||||
sfx_slash (Sound): sound effect indicating close-range attack damage
|
||||
"""
|
||||
def __init__(self, maze, x, y, color):
|
||||
self.maze = maze
|
||||
|
@ -125,7 +124,7 @@ class Enemy:
|
|||
self.spin_speed = self.maze.fps / ENEMY_HP
|
||||
self.spin_queue = self.wound = 0.0
|
||||
|
||||
self.sfx_shot = pygame.mixer.Sound(SFX_SHOT_ENEMY)
|
||||
self.sfx_slash = pygame.mixer.Sound(SFX_SLASH_HERO)
|
||||
|
||||
def get_pos(self):
|
||||
"""Return coordinate of the center of the enemy."""
|
||||
|
@ -200,15 +199,17 @@ class Enemy:
|
|||
return True
|
||||
return False
|
||||
|
||||
def slash(self):
|
||||
def get_slash(self):
|
||||
"""Return the enemy's close-range damage."""
|
||||
if self.spin_queue:
|
||||
d = self.maze.slashd - self.maze.get_distance(*self.get_pos())
|
||||
wound = d / self.maze.hero.R / self.spin_speed
|
||||
if wound >= 0:
|
||||
self.maze.hit(wound, self.color, per_frame=True)
|
||||
return wound
|
||||
return 0.0
|
||||
d = self.maze.slashd - self.maze.get_distance(*self.get_pos())
|
||||
wound = d / self.maze.hero.R
|
||||
return wound if wound > 0 else 0.0
|
||||
|
||||
def slash(self):
|
||||
"""Return the enemy's close-range damage per frame."""
|
||||
wound = self.get_slash() / self.spin_speed
|
||||
if self.spin_queue: self.maze.hit_hero(wound, self.color)
|
||||
return wound
|
||||
|
||||
def draw(self):
|
||||
"""Draw the enemy."""
|
||||
|
@ -224,6 +225,7 @@ class Enemy:
|
|||
self.spin_queue *= self.spin_speed / tmp
|
||||
if not self.spin_queue and not self.fire() and not self.move():
|
||||
self.spin_queue = randsign() * self.spin_speed
|
||||
play(self.sfx_slash, self.get_slash())
|
||||
if abs(self.spin_queue) > 0.5:
|
||||
self.angle += sign(self.spin_queue) * pi / 2 / self.spin_speed
|
||||
self.spin_queue -= sign(self.spin_queue)
|
||||
|
@ -231,12 +233,9 @@ class Enemy:
|
|||
self.angle, self.spin_queue = pi / 4, 0.0
|
||||
self.draw()
|
||||
|
||||
def hit(self, wound, per_frame=False):
|
||||
def hit(self, wound):
|
||||
"""Handle the enemy when it's attacked."""
|
||||
self.wound += wound
|
||||
if not per_frame:
|
||||
self.sfx_shot.set_volume(wound)
|
||||
self.sfx_shot.play()
|
||||
|
||||
def die(self):
|
||||
"""Handle the enemy's death."""
|
||||
|
@ -268,10 +267,10 @@ class Chameleon(Enemy):
|
|||
if not self.awake or pygame.time.get_ticks() <= self.visible:
|
||||
Enemy.draw(self)
|
||||
|
||||
def hit(self, wound, per_frame=False):
|
||||
def hit(self, wound):
|
||||
"""Handle the Chameleon when it's attacked."""
|
||||
self.visible = pygame.time.get_ticks() + 1000//ENEMY_SPEED
|
||||
Enemy.hit(self, wound, per_frame)
|
||||
Enemy.hit(self, wound)
|
||||
|
||||
|
||||
class Plum(Enemy):
|
||||
|
|
|
@ -25,8 +25,11 @@ from pkg_resources import resource_filename
|
|||
|
||||
ICON = image.load(resource_filename('brutalmaze', 'icon.png'))
|
||||
MUSIC = resource_filename('brutalmaze', 'soundfx/music.ogg')
|
||||
SFX_SLASH_ENEMY = resource_filename('brutalmaze', 'soundfx/slash-enemy.ogg')
|
||||
SFX_SLASH_HERO = resource_filename('brutalmaze', 'soundfx/slash-hero.ogg')
|
||||
SFX_SHOT_ENEMY = resource_filename('brutalmaze', 'soundfx/shot-enemy.ogg')
|
||||
SFX_SHOT_HERO = resource_filename('brutalmaze', 'soundfx/shot-hero.ogg')
|
||||
SFX_MISSED = resource_filename('brutalmaze', 'soundfx/missed.ogg')
|
||||
SFX_LOSE = resource_filename('brutalmaze', 'soundfx/lose.ogg')
|
||||
|
||||
UP = (K_UP, K_w)
|
||||
|
|
|
@ -24,7 +24,7 @@ from pygame.locals import *
|
|||
|
||||
from .constants import *
|
||||
from .maze import Maze
|
||||
from .utils import some
|
||||
from .misc import some
|
||||
|
||||
|
||||
def main():
|
||||
|
|
|
@ -25,10 +25,12 @@ from random import choice, getrandbits, uniform
|
|||
|
||||
import pygame
|
||||
from pygame import RESIZABLE
|
||||
from pygame.mixer import Sound, set_num_channels
|
||||
from pygame.time import get_ticks
|
||||
|
||||
from .characters import Hero, new_enemy
|
||||
from .constants import *
|
||||
from .utils import round2, sign, regpoly, fill_aapolygon
|
||||
from .misc import round2, sign, regpoly, fill_aapolygon, play
|
||||
from .weapons import Bullet
|
||||
|
||||
|
||||
|
@ -73,7 +75,11 @@ class Maze:
|
|||
enemies (list of Enemy): alive enemies
|
||||
hero (Hero): the hero
|
||||
next_move (int): the tick that the hero gets mobilized
|
||||
next_slashfx (int): the tick to play next slash effect of the hero
|
||||
slashd (float): minimum distance for slashes to be effective
|
||||
sfx_slash (Sound): sound effect indicating an enemy get slashed
|
||||
sfx_shot (Sound): sound effect indicating an enemy get shot
|
||||
sfx_lose (Sound): sound effect to be played when you lose
|
||||
"""
|
||||
def __init__(self, size, fps):
|
||||
self.w, self.h = size
|
||||
|
@ -96,7 +102,12 @@ class Maze:
|
|||
self.add_enemy()
|
||||
self.hero = Hero(self.surface, fps)
|
||||
self.map[MIDDLE][MIDDLE] = HERO
|
||||
self.next_move, self.slashd = 0, self.hero.R + self.distance/SQRT2
|
||||
self.next_move = self.next_slashfx = 0
|
||||
self.slashd = self.hero.R + self.distance/SQRT2
|
||||
|
||||
self.sfx_slash = Sound(SFX_SLASH_ENEMY)
|
||||
self.sfx_shot = Sound(SFX_SHOT_ENEMY)
|
||||
self.sfx_lose = Sound(SFX_LOSE)
|
||||
|
||||
def add_enemy(self):
|
||||
"""Add enough enemies."""
|
||||
|
@ -104,7 +115,8 @@ class Maze:
|
|||
if self.map[i][j] == WALL]
|
||||
plums = [e for e in self.enemies if e.color == 'Plum' and e.awake]
|
||||
plum = choice(plums) if plums else None
|
||||
while walls and len(self.enemies) < log(self.score, INIT_SCORE):
|
||||
num = log(self.score, INIT_SCORE)
|
||||
while walls and len(self.enemies) < num:
|
||||
x, y = choice(walls)
|
||||
if all(self.map[x + a][y + b] == WALL for a, b in ADJACENT_GRIDS):
|
||||
continue
|
||||
|
@ -114,6 +126,7 @@ class Maze:
|
|||
walls.remove((x, y))
|
||||
else:
|
||||
self.map[x][y] = WALL
|
||||
set_num_channels(int(num * 3))
|
||||
|
||||
def get_pos(self, x, y):
|
||||
"""Return coordinate of the center of the grid (x, y)."""
|
||||
|
@ -183,14 +196,11 @@ class Maze:
|
|||
"""
|
||||
return ((self.x-x)**2 + (self.y-y)**2)**0.5
|
||||
|
||||
def hit(self, wound, color, per_frame=False):
|
||||
def hit_hero(self, wound, color):
|
||||
"""Handle the hero when he loses HP."""
|
||||
if not per_frame:
|
||||
self.hero.sfx_shot.set_volume(wound)
|
||||
self.hero.sfx_shot.play()
|
||||
fx = (uniform(0, sum(self.enemy_weights.values()))
|
||||
< self.enemy_weights[color])
|
||||
time = pygame.time.get_ticks()
|
||||
time = get_ticks()
|
||||
if (color == 'Butter' or color == 'ScarletRed') and fx:
|
||||
self.hero.wound += wound * 2.5
|
||||
elif color == 'Orange' and fx:
|
||||
|
@ -207,12 +217,15 @@ class Maze:
|
|||
"""Handle close-range attacks."""
|
||||
for enemy in self.enemies: enemy.slash()
|
||||
if not self.hero.spin_queue: return
|
||||
unit, killist = self.distance/SQRT2 * self.hero.spin_speed, []
|
||||
killist = []
|
||||
for i, enemy in enumerate(self.enemies):
|
||||
x, y = enemy.get_pos()
|
||||
d = self.get_distance(x, y)
|
||||
if d <= self.slashd:
|
||||
enemy.hit((self.slashd-d) / unit, per_frame=True)
|
||||
d = self.slashd - self.get_distance(*enemy.get_pos())
|
||||
if d > 0:
|
||||
wound, time = d * SQRT2 / self.distance, get_ticks()
|
||||
if time >= self.next_slashfx:
|
||||
play(self.sfx_slash, wound)
|
||||
self.next_slashfx = time + ATTACK_SPEED
|
||||
enemy.hit(wound / self.hero.spin_speed)
|
||||
if enemy.wound >= ENEMY_HP:
|
||||
self.score += enemy.wound
|
||||
enemy.die()
|
||||
|
@ -222,7 +235,7 @@ class Maze:
|
|||
|
||||
def track_bullets(self):
|
||||
"""Handle the bullets."""
|
||||
fallen, time = [], pygame.time.get_ticks()
|
||||
fallen, time = [], get_ticks()
|
||||
if (self.hero.firing and not self.hero.slashing
|
||||
and time >= self.hero.next_strike):
|
||||
self.hero.next_strike = time + ATTACK_SPEED
|
||||
|
@ -240,6 +253,7 @@ class Maze:
|
|||
fallen.append(i)
|
||||
continue
|
||||
for j, enemy in enumerate(self.enemies):
|
||||
if not enemy.awake: continue
|
||||
x, y = enemy.get_pos()
|
||||
if bullet.get_distance(x, y) < self.distance:
|
||||
enemy.hit(wound)
|
||||
|
@ -247,10 +261,15 @@ class Maze:
|
|||
self.score += enemy.wound
|
||||
enemy.die()
|
||||
self.enemies.pop(j)
|
||||
play(self.sfx_shot, wound)
|
||||
fallen.append(i)
|
||||
break
|
||||
elif bullet.get_distance(self.x, self.y) < self.distance:
|
||||
if not self.hero.spin_queue: self.hit(wound, bullet.color)
|
||||
if self.hero.spin_queue:
|
||||
play(bullet.sfx_missed, wound)
|
||||
else:
|
||||
self.hit_hero(wound, bullet.color)
|
||||
play(bullet.sfx_hit, wound)
|
||||
fallen.append(i)
|
||||
for i in reversed(fallen): self.bullets.pop(i)
|
||||
|
||||
|
@ -298,7 +317,7 @@ class Maze:
|
|||
|
||||
def move(self, x, y, fps):
|
||||
"""Command the hero to move faster in the given direction."""
|
||||
stunned = pygame.time.get_ticks() < self.next_move
|
||||
stunned = get_ticks() < self.next_move
|
||||
velocity = self.distance * HERO_SPEED / fps
|
||||
accel = velocity * HERO_SPEED / fps
|
||||
if stunned or not x:
|
||||
|
@ -344,4 +363,4 @@ class Maze:
|
|||
self.hero.dead = True
|
||||
self.hero.slashing = self.hero.firing = False
|
||||
self.vx = self.vy = 0.0
|
||||
pygame.mixer.Sound(SFX_LOSE).play()
|
||||
self.sfx_lose.play()
|
||||
|
|
|
@ -81,3 +81,9 @@ def choices(d):
|
|||
num = uniform(0, cum_weights[-1])
|
||||
for i, w in enumerate(cum_weights):
|
||||
if num <= w: return population[i]
|
||||
|
||||
|
||||
def play(sound, volume):
|
||||
"""Play a pygame.mixer.Sound at the given volume."""
|
||||
sound.set_volume(volume)
|
||||
sound.play()
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -22,9 +22,10 @@ __doc__ = 'brutalmaze module for weapon classes'
|
|||
from math import cos, sin
|
||||
|
||||
from pygame.time import get_ticks
|
||||
from pygame.mixer import Sound
|
||||
|
||||
from .constants import BULLET_LIFETIME, BULLET_SPEED, ENEMY_HP, TANGO
|
||||
from .utils import regpoly, fill_aapolygon
|
||||
from .constants import *
|
||||
from .misc import regpoly, fill_aapolygon
|
||||
|
||||
|
||||
class Bullet:
|
||||
|
@ -36,11 +37,18 @@ class Bullet:
|
|||
angle (float): angle of the direction the bullet pointing (in radians)
|
||||
color (str): bullet's color name
|
||||
fall_time (int): the tick that the bullet will fall down
|
||||
sfx_hit (Sound): sound effect indicating the bullet hits the target
|
||||
sfx_missed (Sound): sound effect indicating the bullet hits the target
|
||||
"""
|
||||
def __init__(self, surface, x, y, angle, color):
|
||||
self.surface = surface
|
||||
self.x, self.y, self.angle, self.color = x, y, angle, color
|
||||
self.fall_time = get_ticks() + BULLET_LIFETIME
|
||||
# Sound effects of bullets shot by hero are stored in Maze to avoid
|
||||
# unnecessary duplication
|
||||
if color != 'Aluminium':
|
||||
self.sfx_hit = Sound(SFX_SHOT_HERO)
|
||||
self.sfx_missed = Sound(SFX_MISSED)
|
||||
|
||||
def update(self, fps, distance):
|
||||
"""Update the bullet."""
|
||||
|
|
Loading…
Reference in New Issue