changeset 388:ac2891afb0bb

Make particles behave as in the original game.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Sun, 21 Oct 2012 23:02:40 +0200
parents e1f5dcd4b83e
children eef492100f4c
files pytouhou/game/bullet.pyx pytouhou/game/effect.py pytouhou/game/enemy.py pytouhou/game/game.py pytouhou/game/player.py
diffstat 5 files changed, 31 insertions(+), 62 deletions(-) [+]
line wrap: on
line diff
--- a/pytouhou/game/bullet.pyx
+++ b/pytouhou/game/bullet.pyx
@@ -135,7 +135,7 @@ cdef class Bullet(object):
 
     def collide(Bullet self):
         self.cancel()
-        self._game.new_particle((self.x, self.y), 1, 3., 256) #TODO: find the real size.
+        self._game.new_particle((self.x, self.y), 10, 256) #TODO: find the real size.
 
 
     def cancel(Bullet self):
--- a/pytouhou/game/effect.py
+++ b/pytouhou/game/effect.py
@@ -16,7 +16,6 @@
 from pytouhou.game.sprite import Sprite
 from pytouhou.vm.anmrunner import ANMRunner
 from pytouhou.utils.interpolator import Interpolator
-from math import pi
 
 
 
@@ -42,64 +41,30 @@ class Effect(object):
 
 
 
-class Particle(object):
-    def __init__(self, start_pos, index, anm_wrapper, size, amp, game):
-        self._game = game
+class Particle(Effect):
+    def __init__(self, pos, index, anm_wrapper, amp, game, reverse=False, duration=24):
+        Effect.__init__(self, pos, index, anm_wrapper)
 
-        self.sprite = Sprite()
-        self.sprite.anm, self.sprite.texcoords = anm_wrapper.get_sprite(index)
-        self.removed = False
-        self.objects = [self]
-
-        self.x, self.y = start_pos
         self.frame = 0
-        self.sprite.alpha = 128
-        self.sprite.blendfunc = 1
-        self.sprite.rescale = (size, size)
+        self.duration = duration
 
-        self.pos_interpolator = None
-        self.scale_interpolator = None
-        self.rotations_interpolator = None
-        self.alpha_interpolator = None
-
-        self.amp = amp
-
+        random_pos = (self.x + amp * game.prng.rand_double() - amp / 2,
+                      self.y + amp * game.prng.rand_double() - amp / 2)
 
-    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(self.sprite.rescale, 0,
-                                               (0., 0.), 24)
-        self.rotations_interpolator = Interpolator(self.sprite.rotations_3d, 0,
-                                                   (0., 0., 2*pi), 24)
-        self.alpha_interpolator = Interpolator((self.sprite.alpha,), 0,
-                                               (0.,), 24)
+        if not reverse:
+            self.pos_interpolator = Interpolator((self.x, self.y), 0,
+                                                 random_pos, duration, formula=(lambda x: 2. * x - x ** 2))
+        else:
+            self.pos_interpolator = Interpolator(random_pos, 0,
+                                                 (self.x, self.y), duration, formula=(lambda x: 2. * x - x ** 2))
+            self.x, self.y = random_pos
 
 
     def update(self):
-        if self.frame == 0:
-            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
+        Effect.update(self)
 
-            self.rotations_interpolator.update(self.frame)
-            self.sprite.rotations_3d = self.rotations_interpolator.values
-
-            self.alpha_interpolator.update(self.frame)
-            self.sprite.alpha, = self.alpha_interpolator.values
-
-            self.sprite.changed = True
-
-        if self.frame == 24:
-            self.removed = True
+        self.pos_interpolator.update(self.frame)
+        self.x, self.y = self.pos_interpolator.values
 
         self.frame += 1
 
--- a/pytouhou/game/enemy.py
+++ b/pytouhou/game/enemy.py
@@ -236,8 +236,9 @@ class Enemy(object):
         if color == 0:
             if self._game.stage in [1, 2, 7]:
                 color = 3
+        color += 9
         for i in range(number):
-            self._game.new_particle((self.x, self.y), color, 3., 256) #TODO: find the real size.
+            self._game.new_particle((self.x, self.y), color, 256) #TODO: find the real size.
 
 
     def set_aux_anm(self, number, script):
--- a/pytouhou/game/game.py
+++ b/pytouhou/game/game.py
@@ -20,8 +20,7 @@ from pytouhou.vm.msgrunner import MSGRun
 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
-from pytouhou.game.effect import Particle
+from pytouhou.game.effect import Effect, Particle
 from pytouhou.game.text import Text
 
 
@@ -185,12 +184,16 @@ class Game(object):
                 enemy.death_callback = -1
 
 
-    def new_effect(self, pos, anim, anm_wrapper=None):
-        self.effects.append(Effect(pos, anim, anm_wrapper or self.etama4))
+    def new_effect(self, pos, anim, anm_wrapper=None, number=1):
+        number = min(number, self.nb_bullets_max - len(self.effects))
+        for i in xrange(number):
+            self.effects.append(Effect(pos, anim, anm_wrapper or 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, amp, self))
+    def new_particle(self, pos, anim, amp, number=1, reverse=False, duration=24):
+        number = min(number, self.nb_bullets_max - len(self.effects))
+        for i in xrange(number):
+            self.effects.append(Particle(pos, anim, self.etama4, amp, self, reverse=reverse, duration=duration))
 
 
     def new_enemy(self, pos, life, instr_type, bonus_dropped, die_score):
@@ -333,7 +336,7 @@ class Game(object):
                     player.state.score += 500 #TODO
                     player.play_sound('graze')
                     self.modify_difficulty(+6) #TODO
-                    self.new_particle((px, py), 0, .8, 192) #TODO
+                    self.new_particle((px, py), 9, 192) #TODO
 
             for bullet in self.bullets:
                 if bullet.state != LAUNCHED:
@@ -357,7 +360,7 @@ class Game(object):
                     player.state.score += 500 # found experimentally
                     player.play_sound('graze')
                     self.modify_difficulty(+6)
-                    self.new_particle((px, py), 0, .8, 192) #TODO: find the real size and range.
+                    self.new_particle((px, py), 9, 192) #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
@@ -104,7 +104,7 @@ class Player(object):
             self._game.modify_difficulty(-1600)
             self.play_sound('pldead00')
             for i in range(16):
-                self._game.new_particle((self.state.x, self.state.y), 2, 4., 256) #TODO: find the real size and range.
+                self._game.new_particle((self.state.x, self.state.y), 11, 256) #TODO: find the real size and range.
 
 
     def start_focusing(self):