# HG changeset patch # User Emmanuel Gil Peyrot # Date 1319214556 25200 # Node ID ea2ad94c33a093ba5ac906e1964adc7ec055cad5 # Parent 2f3665a77f114b2e7b784be191f2e8ef5a56ba24 Implement player death. diff --git a/pytouhou/game/game.py b/pytouhou/game/game.py --- a/pytouhou/game/game.py +++ b/pytouhou/game/game.py @@ -33,7 +33,7 @@ class Game(object): self.item_types = item_types self.characters = characters - self.players = [Player(player_state, characters[player_state.character]) for player_state in player_states] + self.players = [Player(player_state, characters[player_state.character], self) for player_state in player_states] self.enemies = [] self.effects = [] self.bullets = [] @@ -54,12 +54,12 @@ class Game(object): self.ecl_runner = ECLMainRunner(ecl, self) - def drop_bonus(self, x, y, _type): + def drop_bonus(self, x, y, _type, end_pos=None): player = self.players[0] #TODO if _type > 6: return item_type = self.item_types[_type] - item = Item((x, y), item_type, self) + item = Item((x, y), item_type, self, end_pos=end_pos) self.items.append(item) @@ -121,6 +121,9 @@ class Game(object): # 4. Check for collisions! #TODO for player in self.players: + if not player.state.touchable: + continue + px, py = player.x, player.y phalf_size = player.hitbox_half_size px1, px2 = px - phalf_size, px + phalf_size @@ -135,7 +138,8 @@ class Game(object): if not (bx2 < px1 or bx1 > px2 or by2 < py1 or by1 > py2): bullet.collide() - player.collide() + if player.state.invulnerable_time == 0: + player.collide() for enemy in self.enemies: half_size_x, half_size_y = enemy.hitbox_half_size @@ -146,7 +150,8 @@ class Game(object): if enemy.touchable and not (bx2 < px1 or bx1 > px2 or by2 < py1 or by1 > py2): enemy.on_collide() - player.collide() + if player.state.invulnerable_time == 0: + player.collide() for item in self.items: half_size = item.hitbox_half_size @@ -174,6 +179,7 @@ class Game(object): or by2 < ey1 or by1 > ey2): bullet.collide() enemy.on_attack(bullet) + player.state.score += 90 # found experimentally # 5. Cleaning self.cleanup() diff --git a/pytouhou/game/player.py b/pytouhou/game/player.py --- a/pytouhou/game/player.py +++ b/pytouhou/game/player.py @@ -14,6 +14,7 @@ from pytouhou.game.sprite import Sprite +from pytouhou.game.enemy import Effect from pytouhou.vm.anmrunner import ANMRunner @@ -35,11 +36,15 @@ class PlayerState(object): self.x = 192.0 self.y = 384.0 + self.invulnerable_time = 60 + self.touchable = True + class Player(object): - def __init__(self, state, character): + def __init__(self, state, character, game): self._sprite = None self._anmrunner = None + self._game = game self.hitbox_half_size = character.hitbox_size / 2. @@ -50,6 +55,8 @@ class Player(object): self.set_anim(0) + self.death_time = 0 + @property def x(self): @@ -68,11 +75,10 @@ class Player(object): def collide(self): - self.state.lives -= 1 - self.state.x = 192.0 - self.state.y = 384.0 - #TODO: animation - #TODO: set invulnerability. + if not self.state.invulnerable_time and not self.death_time and self.state.touchable: # Border Between Life and Death + self.death_time = self._game.frame + eff00 = self._game.resource_loader.get_anm_wrapper(('eff00.anm',)) + self._game.effects.append(Effect((self.state.x, self.state.y), 2, eff00)) def collect(self, item): @@ -82,29 +88,83 @@ class Player(object): def update(self, keystate): - try: - dx, dy = {16: (0.0, -1.0), 32: (0.0, 1.0), 64: (-1.0, 0.0), 128: (1.0, 0.0), - 16|64: (-SQ2, -SQ2), 16|128: (SQ2, -SQ2), - 32|64: (-SQ2, SQ2), 32|128: (SQ2, SQ2)}[keystate & (16|32|64|128)] - except KeyError: - speed = 0.0 - dx, dy = 0.0, 0.0 - else: - speed = self.character.focused_speed if keystate & 4 else self.character.speed - dx, dy = dx * speed, dy * speed + if self.death_time == 0 or self._game.frame - self.death_time > 60: + try: + dx, dy = {16: (0.0, -1.0), 32: (0.0, 1.0), 64: (-1.0, 0.0), 128: (1.0, 0.0), + 16|64: (-SQ2, -SQ2), 16|128: (SQ2, -SQ2), + 32|64: (-SQ2, SQ2), 32|128: (SQ2, SQ2)}[keystate & (16|32|64|128)] + except KeyError: + speed = 0.0 + dx, dy = 0.0, 0.0 + else: + speed = self.character.focused_speed if keystate & 4 else self.character.speed + dx, dy = dx * speed, dy * speed + + if dx < 0 and self.direction != -1: + self.set_anim(1) + self.direction = -1 + elif dx > 0 and self.direction != +1: + self.set_anim(3) + self.direction = +1 + elif dx == 0 and self.direction is not None: + self.set_anim({-1: 2, +1: 4}[self.direction]) + self.direction = None + + self.state.x += dx + self.state.y += dy + + if self.state.invulnerable_time > 0: + self.state.invulnerable_time -= 1 + + m = self.state.invulnerable_time % 8 + if m == 0: + self._sprite.color = (255, 255, 255) + self._sprite._changed = True + elif m == 2: + self._sprite.color = (64, 64, 64) + self._sprite._changed = True - if dx < 0 and self.direction != -1: - self.set_anim(1) - self.direction = -1 - elif dx > 0 and self.direction != +1: - self.set_anim(3) - self.direction = +1 - elif dx == 0 and self.direction is not None: - self.set_anim({-1: 2, +1: 4}[self.direction]) - self.direction = None + if self.death_time: + time = self._game.frame - self.death_time + if time == 6: # too late, you are dead :( + self._game.drop_bonus(self.state.x, self.state.y, 2, end_pos=None) #TODO: find the formula + for i in range(5): + self._game.drop_bonus(self.state.x, self.state.y, 0, end_pos=None) #TODO: find the formula + self.state.lives -= 1 + + elif time == 7: + self.state.touchable = False + self._sprite.mirrored = False + self._sprite.fade(24, 128, lambda x: x) + self._sprite.blendfunc = 1 + self._sprite.scale_in(24, 0., 2., lambda x: x) + + elif time == 31: + self.state.x = 192.0 + self.state.y = 384.0 + self.direction = None - self.state.x += dx - self.state.y += dy + self._sprite = Sprite() + self._anmrunner = ANMRunner(self.anm_wrapper, 0, self._sprite) + self._sprite.alpha = 128 + self._sprite.rescale = 0., 2. + self._sprite.fade(30, 255, lambda x: x) + self._sprite.blendfunc = 1 + self._sprite.scale_in(30, 1., 1., lambda x: x) + self._anmrunner.run_frame() + + elif time == 60: # respawned + self.state.touchable = True + self.state.invulnerable_time = 240 + self._sprite.blendfunc = 0 + + if time > 30: + for bullet in self._game.bullets: + bullet.cancel() + + if time > 90: # start the bullet hell again + self.death_time = 0 + self._anmrunner.run_frame()