# HG changeset patch # User Emmanuel Gil Peyrot # Date 1379787999 -7200 # Node ID 887de13094914d65ff153590fd4e90a4cb46e723 # Parent 2276229282fdb81e0214c8af541c76b6d96aade2 Add friendly fire in netplay. diff --git a/eosd b/eosd --- a/eosd +++ b/eosd @@ -48,6 +48,7 @@ parser.add_argument('--verbosity', metav parser.add_argument('--game', metavar='GAME', choices=['EoSD'], default='EoSD', help='Select the game engine to use.') parser.add_argument('--port', metavar='PORT', type=int, default=0, help='Local port to use for netplay') parser.add_argument('--remote', metavar='REMOTE', default=None, help='Remote address') +parser.add_argument('--no-friendly-fire', action='store_false', help='Allow friendly-fire during netplay.') args = parser.parse_args() @@ -101,7 +102,7 @@ class GameBossRush(Game): def main(window, path, data, stage_num, rank, character, replay, save_filename, skip_replay, boss_rush, debug, enable_background, enable_particles, - enable_music, hints, verbosity, port, remote): + enable_music, hints, verbosity, port, remote, friendly_fire): resource_loader = Loader(path) @@ -153,12 +154,12 @@ def main(window, path, data, stage_num, prng = Random(0) con = Network(port, addr, selected_player) - states = [PlayerState(character=1, power=default_power, continues=continues), - PlayerState(character=3, power=default_power, continues=continues)] + states = [PlayerState(0, character=1, power=default_power, continues=continues), + PlayerState(1, character=3, power=default_power, continues=continues)] else: con = None selected_player = 0 - states = [PlayerState(character=character, power=default_power, continues=continues)] + states = [PlayerState(0, character=character, power=default_power, continues=continues)] if hints: with open(hints, 'rb') as file: @@ -204,7 +205,9 @@ def main(window, path, data, stage_num, hints_stage = hints.stages[stage_num - 1] if hints else None - game = game_class(resource_loader, states, stage_num, rank, difficulty, common, prng=prng, hints=hints_stage) + game = game_class(resource_loader, states, stage_num, rank, difficulty, + common, prng=prng, hints=hints_stage, + friendly_fire=friendly_fire) if not enable_particles: def new_particle(pos, anim, amp, number=1, reverse=False, duration=24): @@ -251,7 +254,8 @@ with SDL(): main(window, args.path, tuple(args.data), args.stage, args.rank, args.character, args.replay, args.save_replay, args.skip_replay, args.boss_rush, args.debug, args.no_background, args.no_particles, - args.no_music, args.hints, args.verbosity, args.port, args.remote) + args.no_music, args.hints, args.verbosity, args.port, args.remote, + args.no_friendly_fire) import gc gc.collect() diff --git a/pytouhou/game/bullet.pxd b/pytouhou/game/bullet.pxd --- a/pytouhou/game/bullet.pxd +++ b/pytouhou/game/bullet.pxd @@ -12,7 +12,7 @@ cdef class Bullet(Element): cdef public State state cdef public unsigned long flags, frame, sprite_idx_offset, damage cdef public double dx, dy, angle, speed - cdef public bint player_bullet, was_visible, grazed + cdef public bint was_visible, grazed cdef public Element target cdef public BulletType _bullet_type cdef public list attributes @@ -20,6 +20,7 @@ cdef class Bullet(Element): cdef double hitbox[2] cdef Interpolator speed_interpolator cdef Game _game + cdef long player cdef bint is_visible(self, unsigned int screen_width, unsigned int screen_height) except? False cpdef set_anim(self, sprite_idx_offset=*) diff --git a/pytouhou/game/bullet.pyx b/pytouhou/game/bullet.pyx --- a/pytouhou/game/bullet.pyx +++ b/pytouhou/game/bullet.pyx @@ -21,7 +21,7 @@ from pytouhou.game.sprite cimport Sprite cdef class Bullet(Element): def __init__(self, pos, BulletType bullet_type, unsigned long sprite_idx_offset, double angle, double speed, attributes, unsigned long flags, target, Game game, - bint player_bullet=False, unsigned long damage=0, tuple hitbox=None): + long player=-1, unsigned long damage=0, tuple hitbox=None): cdef double launch_mult Element.__init__(self, pos) @@ -51,7 +51,7 @@ cdef class Bullet(Element): self.speed = speed self.dx, self.dy = cos(angle) * speed, sin(angle) * speed - self.player_bullet = player_bullet + self.player = player self.damage = damage #TODO @@ -73,7 +73,7 @@ cdef class Bullet(Element): else: self.launch() - if self.player_bullet: + if self.player >= 0: self.sprite.angle = angle - pi else: self.sprite.angle = angle @@ -102,7 +102,7 @@ cdef class Bullet(Element): bt = self._bullet_type self.sprite = Sprite() - if self.player_bullet: + if self.player >= 0: self.sprite.angle = self.angle - pi else: self.sprite.angle = self.angle @@ -130,7 +130,7 @@ cdef class Bullet(Element): # Cancel animation bt = self._bullet_type self.sprite = Sprite() - if self.player_bullet: + if self.player >= 0: self.sprite.angle = self.angle - pi else: self.sprite.angle = self.angle diff --git a/pytouhou/game/enemy.pyx b/pytouhou/game/enemy.pyx --- a/pytouhou/game/enemy.pyx +++ b/pytouhou/game/enemy.pyx @@ -336,7 +336,6 @@ cdef class Enemy(Element): continue half_size[0] = laser.hitbox[0] - half_size[1] = laser.hitbox[1] lx, ly = laser.x, laser.y * 2. lx1, lx2 = lx - half_size[0], lx + half_size[0] diff --git a/pytouhou/game/game.pxd b/pytouhou/game/game.pxd --- a/pytouhou/game/game.pxd +++ b/pytouhou/game/game.pxd @@ -12,6 +12,8 @@ cdef class Game: cdef public bint time_stop, msg_wait cdef public unsigned short deaths_count, next_bonus + cdef bint friendly_fire + cdef list msg_sprites(self) cdef list lasers_sprites(self) cdef void modify_difficulty(self, long diff) except * diff --git a/pytouhou/game/game.pyx b/pytouhou/game/game.pyx --- a/pytouhou/game/game.pyx +++ b/pytouhou/game/game.pyx @@ -26,7 +26,8 @@ from pytouhou.game.face import Face cdef class Game: def __init__(self, players, long stage, long rank, long difficulty, bullet_types, laser_types, item_types, long nb_bullets_max=0, long width=384, - long height=448, prng=None, interface=None, hints=None): + long height=448, prng=None, interface=None, hints=None, + friendly_fire=True): self.width, self.height = width, height self.nb_bullets_max = nb_bullets_max @@ -72,6 +73,7 @@ cdef class Game: self.deaths_count = self.prng.rand_uint16() % 3 self.next_bonus = self.prng.rand_uint16() % 8 + self.friendly_fire = friendly_fire self.last_keystate = 0 @@ -386,6 +388,7 @@ cdef class Game: cdef Item item cdef PlayerLaser player_laser cdef Laser laser + cdef PlayerLaser plaser cdef double player_pos[2] if self.time_stop: @@ -458,6 +461,40 @@ cdef class Game: #TODO: display a static particle during one frame at # 12 pixels of the player, in the axis of the “collision”. + # Check for friendly-fire only if there are multiple players. + if self.friendly_fire and len(self.players) > 1: + for bullet in self.players_bullets: + if bullet.state != LAUNCHED: + continue + + if bullet.player == player_state.number: + continue + + bhalf_width = bullet.hitbox[0] + bhalf_height = bullet.hitbox[1] + bx, by = bullet.x, bullet.y + bx1, bx2 = bx - bhalf_width, bx + bhalf_width + by1, by2 = by - bhalf_height, by + bhalf_height + + if not (bx2 < px1 or bx1 > px2 + or by2 < py1 or by1 > py2): + bullet.collide() + if player_state.invulnerable_time == 0: + player.collide() + + for plaser in self.players_lasers: + if not plaser: + continue + + lhalf_width = plaser.hitbox[0] + lx, ly = plaser.x, plaser.y * 2. + lx1, lx2 = lx - lhalf_width, lx + lhalf_width + + if not (lx2 < px1 or lx1 > px2 + or ly < py1): + if player_state.invulnerable_time == 0: + player.collide() + #TODO: is it the right place? if py < 128 and player_state.power >= 128: #TODO: check py. self.autocollect(player) diff --git a/pytouhou/game/player.pxd b/pytouhou/game/player.pxd --- a/pytouhou/game/player.pxd +++ b/pytouhou/game/player.pxd @@ -7,6 +7,7 @@ cdef class PlayerState: cdef public long character, score, effective_score, lives, bombs, power cdef public long graze, points + cdef long number cdef long invulnerable_time, power_bonus, continues, continues_used, miss, cdef long bombs_used diff --git a/pytouhou/game/player.pyx b/pytouhou/game/player.pyx --- a/pytouhou/game/player.pyx +++ b/pytouhou/game/player.pyx @@ -27,8 +27,9 @@ class GameOver(Exception): cdef class PlayerState: - def __init__(self, long character=0, long score=0, long power=0, - long lives=2, long bombs=3, long continues=0): + def __init__(self, long number, long character=0, long score=0, + long power=0, long lives=2, long bombs=3, long continues=0): + self.number = number self.character = character # ReimuA/ReimuB/MarisaA/MarisaB/... self.score = score @@ -161,13 +162,13 @@ cdef class Player(Element): bullets.append(Bullet((x, y), bullet_type, 0, shot.angle, shot.speed, (-1, 0, 0, 0, 0.15, -pi/2., 0., 0.), - 16, self, self._game, player_bullet=True, + 16, self, self._game, player=self.state.number, damage=shot.damage, hitbox=shot.hitbox)) else: bullets.append(Bullet((x, y), bullet_type, 0, shot.angle, shot.speed, (0, 0, 0, 0, 0., 0., 0., 0.), - 0, self, self._game, player_bullet=True, + 0, self, self._game, player=self.state.number, damage=shot.damage, hitbox=shot.hitbox)) diff --git a/pytouhou/games/eosd.py b/pytouhou/games/eosd.py --- a/pytouhou/games/eosd.py +++ b/pytouhou/games/eosd.py @@ -82,7 +82,7 @@ class EoSDCommon(object): class EoSDGame(Game): def __init__(self, resource_loader, player_states, stage, rank, difficulty, common, nb_bullets_max=640, width=384, height=448, prng=None, - hints=None): + hints=None, friendly_fire=True): self.etama = common.etama #XXX try: @@ -124,7 +124,7 @@ class EoSDGame(Game): Game.__init__(self, players, stage, rank, difficulty, common.bullet_types, common.laser_types, common.item_types, nb_bullets_max, width, height, prng, - common.interface, hints) + common.interface, hints, friendly_fire)