changeset 335:2350147cf043

Fix bullet cancellation and removal
author Thibaut Girka <thib@sitedethib.com>
date Sun, 01 Jul 2012 11:43:38 +0200
parents 4eca6130f118
children 72ef7e24b373
files pytouhou/game/bullet.pyx pytouhou/game/enemy.py pytouhou/game/game.py pytouhou/game/player.py
diffstat 4 files changed, 32 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/pytouhou/game/bullet.pyx
+++ b/pytouhou/game/bullet.pyx
@@ -22,7 +22,7 @@ from pytouhou.game.sprite import Sprite
 LAUNCHING, LAUNCHED, CANCELLED = range(3)
 
 cdef class Bullet(object):
-    cdef public unsigned int _state, flags, frame, sprite_idx_offset
+    cdef public unsigned int state, flags, frame, sprite_idx_offset
     cdef public double dx, dy, angle, speed #TODO
     cdef public object player_bullet, target
     cdef public object _game, _bullet_type
@@ -35,7 +35,7 @@ cdef class Bullet(object):
                        player_bullet=False, damage=0, hitbox=None):
         self._game = game
         self._bullet_type = bullet_type
-        self._state = LAUNCHING
+        self.state = LAUNCHING
         self.sprite = None
         self.anmrunner = None
         self.removed = False
@@ -122,7 +122,7 @@ cdef class Bullet(object):
 
 
     def launch(Bullet self):
-        self._state = LAUNCHED
+        self.state = LAUNCHED
         self.frame = 0
         self.set_anim()
         self.dx, self.dy = cos(self.angle) * self.speed, sin(self.angle) * self.speed
@@ -151,7 +151,7 @@ cdef class Bullet(object):
         self.dx, self.dy = self.dx / 2., self.dy / 2.
 
         # Change update method
-        self._state = CANCELLED
+        self.state = CANCELLED
 
         # Do not use this one for collisions anymore
         if self.player_bullet:
@@ -163,17 +163,17 @@ cdef class Bullet(object):
 
     def update(Bullet self):
         if self.anmrunner is not None and not self.anmrunner.run_frame():
-            if self._state == LAUNCHING:
+            if self.state == LAUNCHING:
                 #TODO: check if it doesn't skip a frame
                 self.launch()
-            elif self._state == CANCELLED:
+            elif self.state == CANCELLED:
                 self.removed = True
             else:
                 self.anmrunner = None
 
-        if self._state == LAUNCHING:
+        if self.state == LAUNCHING:
             pass
-        elif self._state == CANCELLED:
+        elif self.state == CANCELLED:
             pass
         elif self.flags & 1:
             # Initial speed burst
--- a/pytouhou/game/enemy.py
+++ b/pytouhou/game/enemy.py
@@ -20,6 +20,7 @@ from pytouhou.game.bullet import Bullet
 from pytouhou.game.laser import Laser
 from pytouhou.game.effect import Effect
 from math import cos, sin, atan2, pi
+from pytouhou.game.bullet import LAUNCHED
 
 
 class Enemy(object):
@@ -280,6 +281,8 @@ class Enemy(object):
 
         # Check for enemy-bullet collisions
         for bullet in self._game.players_bullets:
+            if bullet.state != LAUNCHED:
+                continue
             half_size = bullet.hitbox_half_size
             bx, by = bullet.x, bullet.y
             bx1, bx2 = bx - half_size[0], bx + half_size[0]
--- a/pytouhou/game/game.py
+++ b/pytouhou/game/game.py
@@ -12,11 +12,14 @@
 ## GNU General Public License for more details.
 ##
 
+from itertools import chain
+
 from pytouhou.utils.random import Random
 
 from pytouhou.vm.eclrunner import ECLMainRunner
 from pytouhou.vm.msgrunner import MSGRunner
 
+from pytouhou.game.bullet import LAUNCHED, CANCELLED
 from pytouhou.game.enemy import Enemy
 from pytouhou.game.item import Item
 from pytouhou.game.effect import Effect
@@ -142,6 +145,13 @@ class Game(object):
                 item.autocollect(player)
 
 
+    def cancel_bullets(self):
+        for bullet in self.bullets:
+            bullet.cancel()
+        for laser in self.lasers:
+            laser.cancel()
+
+
     def change_bullets_into_star_items(self):
         player = self.players[0] #TODO
         item_type = self.item_types[6]
@@ -325,6 +335,9 @@ class Game(object):
                     self.new_particle((px, py), 0, .8, 192) #TODO
 
             for bullet in self.bullets:
+                if bullet.state != LAUNCHED:
+                    continue
+
                 half_size = bullet.hitbox_half_size
                 bx, by = bullet.x, bullet.y
                 bx1, bx2 = bx - half_size[0], bx + half_size[0]
@@ -372,16 +385,19 @@ class Game(object):
 
         self.enemies = [enemy for enemy in self.enemies if not enemy.removed]
 
+        # Update cancelled bullets
+        self.cancelled_bullets = [b for b in chain(self.cancelled_bullets,
+                                                   self.bullets,
+                                                   self.players_bullets)
+                                    if b.state == CANCELLED and not b.removed]
         # Filter out-of-scren bullets
         self.bullets = [bullet for bullet in self.bullets
-                            if not bullet.removed]
+                            if not bullet.removed and bullet.state != CANCELLED]
         self.players_bullets = [bullet for bullet in self.players_bullets
-                            if not bullet.removed]
+                            if not bullet.removed and bullet.state != CANCELLED]
         for i, laser in enumerate(self.players_lasers):
             if laser and laser.removed:
                 self.players_lasers[i] = None
-        self.cancelled_bullets = [bullet for bullet in self.cancelled_bullets
-                            if not bullet.removed]
         self.effects = [effect for effect in self.effects if not effect.removed]
 
         # Filter “timed-out” lasers
--- a/pytouhou/game/player.py
+++ b/pytouhou/game/player.py
@@ -256,10 +256,7 @@ class Player(object):
                 self.sprite.changed = True
 
             if time > 30:
-                for bullet in self._game.bullets:
-                    bullet.cancel()
-                for laser in self._game.lasers:
-                    laser.cancel()
+                self._game.cancel_bullets()
 
             if time > 90: # start the bullet hell again
                 self.death_time = 0