changeset 190:dbe6b7b2d3fc

Fix a few things about particles.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Thu, 27 Oct 2011 15:09:42 -0700
parents ba3297ab3bde
children d2b58a26c908
files pytouhou/game/effect.py pytouhou/game/enemy.py pytouhou/game/game.py pytouhou/game/player.py pytouhou/vm/eclrunner.py
diffstat 5 files changed, 49 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/pytouhou/game/effect.py
+++ b/pytouhou/game/effect.py
@@ -40,36 +40,53 @@ class Effect(object):
 
 
 class Particle(object):
-    def __init__(self, start_pos, index, anm_wrapper, size, end_pos):
+    def __init__(self, start_pos, index, anm_wrapper, size, amp, delay, game):
         self._sprite = Sprite()
         self._sprite.anm, self._sprite.texcoords = anm_wrapper.get_sprite(index)
+        self._game = game
         self._removed = False
 
         self.x, self.y = start_pos
         self.frame = 0
         self._sprite.alpha = 128
         self._sprite.blendfunc = 1
+        self._sprite.rescale = (size, size)
 
-        self.pos_interpolator = Interpolator(start_pos, 0,
+        self.pos_interpolator = None
+        self.scale_interpolator = None
+        self.rotations_interpolator = None
+
+        self.delay = delay
+        self.amp = amp
+
+
+    def set_end_pos(self, amp):
+        end_pos = (self.x + amp * self._game.prng.rand_double() - amp/2,
+                   self.y + amp * self._game.prng.rand_double() - amp/2)
+
+        self.pos_interpolator = Interpolator((self.x, self.y), 0,
                                              end_pos, 24, formula=(lambda x: 2. * x - x ** 2))
-        self.scale_interpolator = Interpolator((size, size), 0,
+        self.scale_interpolator = Interpolator(self._sprite.rescale, 0,
                                                (0., 0.), 24)
-        self.rotations_interpolator = Interpolator((0., 0., 0.), 0,
+        self.rotations_interpolator = Interpolator(self._sprite.rotations_3d, 0,
                                                    (0., 0., 2*pi), 24)
-        self._sprite._changed = True
 
 
     def update(self):
-        self.pos_interpolator.update(self.frame)
-        self.x, self.y = self.pos_interpolator.values
+        if (self.frame == 0 and not self.delay) or (self.frame == 1 and self.delay):
+            self.set_end_pos(self.amp)
+
+        if self.pos_interpolator:
+            self.pos_interpolator.update(self.frame)
+            self.x, self.y = self.pos_interpolator.values
 
-        self.scale_interpolator.update(self.frame)
-        self._sprite.rescale = self.scale_interpolator.values
+            self.scale_interpolator.update(self.frame)
+            self._sprite.rescale = self.scale_interpolator.values
 
-        self.rotations_interpolator.update(self.frame)
-        self._sprite.rotations_3d = self.rotations_interpolator.values
+            self.rotations_interpolator.update(self.frame)
+            self._sprite.rotations_3d = self.rotations_interpolator.values
 
-        self._sprite._changed = True
+            self._sprite._changed = True
 
         if self.frame == 24:
             self._removed = True
--- a/pytouhou/game/enemy.py
+++ b/pytouhou/game/enemy.py
@@ -169,7 +169,7 @@ class Enemy(object):
     def on_attack(self, bullet):
         if self.damageable:
             self.life -= bullet._bullet_type.damage
-            self._game.new_particle((self.x, self.y), 1, 3., 192) #TODO: find the real size and range.
+            self.drop_particles(1, 1)
 
 
     def on_collide(self):
@@ -178,10 +178,16 @@ class Enemy(object):
 
     def die_anim(self):
         self._game.new_death((self.x, self.y), self.death_anim)
-        #TODO: 8 white particles are used only in stage 3 to 6,
-        # in other stages they are 2 red and 6 blue.
-        for i in range(8):
-            self._game.new_particle((self.x, self.y), 0, 3., 192) #TODO: find the real size and range.
+
+
+    def drop_particles(self, number, color):
+        #TODO: white particles are only used in stage 3 to 6,
+        # in other stages they are blue.
+        if color == 0:
+            if self._game.stage in [1, 2, 7]:
+                color = 3
+        for i in range(number):
+            self._game.new_particle((self.x, self.y), color, 4., 256, delay=False) #TODO: find the real size.
 
 
     def set_pos(self, x, y, z):
--- a/pytouhou/game/game.py
+++ b/pytouhou/game/game.py
@@ -84,10 +84,8 @@ class Game(object):
         self.effects.append(Effect(pos, anim, self.etama4))
 
 
-    def new_particle(self, pos, color, size, amp):
-        self.effects.append(Particle(pos, 7 + 4 * color + self.prng.rand_uint16() % 4, self.etama4, size,
-                                     (pos[0] + amp * self.prng.rand_double() - amp/2,
-                                      pos[1] + amp * self.prng.rand_double() - amp/2)))
+    def new_particle(self, pos, color, size, amp, delay=False):
+        self.effects.append(Particle(pos, 7 + 4 * color + self.prng.rand_uint16() % 4, self.etama4, size, amp, delay, self))
 
 
     def new_enemy(self, pos, life, instr_type, bonus_dropped, die_score):
@@ -170,7 +168,7 @@ class Game(object):
                     bullet.grazed = True
                     player.state.graze += 1
                     player.state.score += 500 # found experimentally
-                    self.new_particle((px, py), 0, .8, 192) #TODO: find the real size and range.
+                    self.new_particle((px, py), 0, .8, 192, delay=True) #TODO: find the real size and range.
                     #TODO: display a static particle during one frame at
                     # 12 pixels of the player, in the axis of the “collision”.
 
--- a/pytouhou/game/player.py
+++ b/pytouhou/game/player.py
@@ -78,6 +78,8 @@ class Player(object):
         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
             self._game.new_death((self.state.x, self.state.y), 2)
+            for i in range(16):
+                self._game.new_particle((self.state.x, self.state.y), 2, 4., 256, delay=True) #TODO: find the real size and range.
 
 
     def collect(self, item):
@@ -141,9 +143,6 @@ class Player(object):
                                           end_pos=(self._game.prng.rand_double() * 288 + 48,
                                                    self._game.prng.rand_double() * 192 - 64))
 
-                for i in range(16):
-                    self._game.new_particle((self.state.x, self.state.y), 0, 4., 256) #TODO: find the real size and range.
-
             elif time == 7:
                 self._sprite.mirrored = False
                 self._sprite.fade(24, 128, lambda x: x)
--- a/pytouhou/vm/eclrunner.py
+++ b/pytouhou/vm/eclrunner.py
@@ -129,9 +129,13 @@ class ECLRunner(object):
 
             if death_flags < 4:
                 if enm._bonus_dropped >= 0:
+                    enm.drop_particles(7, 0)
                     self._game.drop_bonus(enm.x, enm.y, enm._bonus_dropped)
                 elif enm._bonus_dropped == -1:
+                    enm.drop_particles(10, 0)
                     self._game.drop_bonus(enm.x, enm.y, self._game.prng.rand_uint16() % 2) #TODO: find the formula in the binary. Can be big power sometimes.
+                else:
+                    enm.drop_particles(4, 0)
 
                 if death_flags == 0:
                     enm._removed = True