Finish adding sound effects (#2)

This commit is contained in:
Nguyễn Gia Phong 2018-01-21 20:38:51 +07:00
parent 966951db60
commit 7fe7311371
14 changed files with 75 additions and 40 deletions

View File

@ -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):

View File

@ -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)

View File

@ -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():

View File

@ -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()

View File

@ -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.

View File

@ -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."""

View File

@ -7,7 +7,7 @@ with open('README.rst') as f:
setup(
name='brutalmaze',
version='0.2.2',
version='0.3.0',
description='A hash and slash game with fast-paced action and a minimalist art style',
long_description=long_description,
url='https://github.com/McSinyx/brutalmaze',