changeset 75:b3bd421bb895

Handle a few more ECL instructions
author Thibaut Girka <thib@sitedethib.com>
date Tue, 30 Aug 2011 16:30:40 +0200
parents adac26098408
children f305c0e406d6
files pytouhou/formats/ecl.py pytouhou/game/enemymanager.py pytouhou/game/sprite.py pytouhou/vm/eclrunner.py
diffstat 4 files changed, 54 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/pytouhou/formats/ecl.py
+++ b/pytouhou/formats/ecl.py
@@ -30,7 +30,7 @@ class ECL(object):
                      6: ('ii', 'set_random_int'),
                      8: ('if', 'set_random_float'),
                      9: ('iff', 'set_random_float2'),
-                     10: ('i', None),
+                     10: ('i', 'store_x'),
                      13: ('iii', 'set_random_int2'),
                      14: ('iii', 'substract_int'),
                      15: ('iii', 'multiply_int'),
@@ -66,7 +66,7 @@ class ECL(object):
                      57: ('ifff', 'move_to'),
                      59: ('iffi', 'move_to2'),
                      61: ('i', 'stop_in'),
-                     63: ('i', None),
+                     63: ('i', 'stop_in_accel'),
                      65: ('ffff', 'set_screen_box'),
                      66: ('', 'clear_screen_box'),
                      67: ('hhiiffffi', 'set_bullet_attributes'),
@@ -104,7 +104,7 @@ class ECL(object):
                      104: ('i', None),
                      105: ('i', 'set_damageable'),
                      106: ('i', 'play_sound'),
-                     107: ('i', None),
+                     107: ('i', 'set_death_flags'),
                      108: ('i', 'set_death_callback?'),
                      109: ('ii', 'memory_write_int'),
                      111: ('i', 'set_life'),
@@ -116,10 +116,10 @@ class ECL(object):
                      117: ('i', 'set_touchable'),
                      118: ('iihh', None),
                      119: ('i', 'drop_bonus'),
-                     120: ('i', None),
+                     120: ('i', 'set_automatic_orientation'),
                      121: ('ii', None),
                      122: ('i', None),
-                     123: ('i', None),
+                     123: ('i', 'skip_frames'),
                      124: ('i', None),
                      125: ('', None),
                      126: ('i', 'set_remaining_lives'),
--- a/pytouhou/game/enemymanager.py
+++ b/pytouhou/game/enemymanager.py
@@ -51,6 +51,8 @@ class Enemy(object):
         self.timeout_callback = None
         self.remaining_lives = -1
 
+        self.automatic_orientation = False
+
         self.bullet_launch_interval = 0
         self.delay_attack = False
 
@@ -108,15 +110,18 @@ class Enemy(object):
             self.interpolator.set_interpolation_start(self.frame, (self.x, self.y))
             self.interpolator.set_interpolation_end(self.frame + duration - 1, (x, y))
 
+            self.speed = 0.
+            self.angle = atan2(y - self.y, x - self.x)
 
-    def stop_in(self, duration):
-        #TODO: interpolation method and start/stop frame
-        # See 97 vs 98 anim conflict
+
+    def stop_in(self, duration, formula):
         if not self.speed_interpolator:
-            self.speed_interpolator = Interpolator((self.speed,))
+            self.speed_interpolator = Interpolator((self.speed,), formula)
             self.speed_interpolator.set_interpolation_start(self.frame, (self.speed,))
             self.speed_interpolator.set_interpolation_end(self.frame + duration, (0.,))
 
+            self.speed = 0.
+
 
     def is_visible(self, screen_width, screen_height):
         if self._sprite:
@@ -211,8 +216,9 @@ class Enemy(object):
                 self._sprite = None
             else:
                 self._sprite.update()
-                if self._sprite._changed:
-                    self._sprite.update_vertices_uvs_colors()
+                if self._sprite._changed or self.automatic_orientation:
+                    angle_base = self.angle if self.automatic_orientation else 0.
+                    self._sprite.update_vertices_uvs_colors(angle_base=angle_base)
 
         self.frame += 1
 
--- a/pytouhou/game/sprite.py
+++ b/pytouhou/game/sprite.py
@@ -88,7 +88,7 @@ class Sprite(object):
             self.offset_interpolator.set_interpolation_end(self.frame + duration - 1, (x, y, z))
 
 
-    def update_vertices_uvs_colors(self, override_width=0, override_height=0):
+    def update_vertices_uvs_colors(self, override_width=0, override_height=0, angle_base=0.):
         if self.fade_interpolator:
             self.fade_interpolator.update(self.frame)
             self.alpha = int(self.fade_interpolator.values[0])
@@ -115,8 +115,11 @@ class Sprite(object):
         vertmat.scale2d(width, height)
         if self.mirrored:
             vertmat.flip()
-        if self.rotations_3d != (0., 0., 0.):
-            rx, ry, rz = self.rotations_3d
+
+        rx, ry, rz = self.rotations_3d
+        rz += angle_base
+
+        if (rx, ry, rz) != (0., 0., 0.):
             if rx:
                 vertmat.rotate_x(-rx)
             if ry:
--- a/pytouhou/vm/eclrunner.py
+++ b/pytouhou/vm/eclrunner.py
@@ -198,6 +198,11 @@ class ECLRunner(object):
         self._setval(variable_id, self._getval(minval) + self._getval(amp) * self._game_state.prng.rand_double())
 
 
+    @instruction(10)
+    def store_x(self, variable_id):
+        self._setval(variable_id, self._enemy.x)
+
+
     @instruction(13)
     def set_random_int2(self, variable_id, minval, amp):
         self._setval(variable_id, int(self._getval(minval)) + int(self._getval(amp)) * self._game_state.prng.rand_double())
@@ -382,13 +387,17 @@ class ECLRunner(object):
 
     @instruction(59)
     def move_to2(self, duration, x, y, z):
-        #TODO: not accurate
-        self._enemy.move_to(duration, x, y, z, lambda x: 1.0014 * x ** 2 - 0.0012 * x)
+        self._enemy.move_to(duration, x, y, z, lambda x: x ** 2)
 
 
     @instruction(61)
     def stop_in(self, duration):
-        self._enemy.stop_in(duration)
+        self._enemy.stop_in(duration, lambda x: x)
+
+
+    @instruction(63)
+    def stop_in_accel(self, duration):
+        self._enemy.stop_in(duration, lambda x: 1. - x)
 
 
     @instruction(65)
@@ -459,8 +468,13 @@ class ECLRunner(object):
 
 
     @instruction(105)
-    def set_damageable(self, vulnerable):
-        self._enemy.damageable = bool(vulnerable & 1)
+    def set_damageable(self, damageable):
+        self._enemy.damageable = bool(damageable & 1)
+
+
+    @instruction(107)
+    def set_death_flags(self, death_flags):
+        self._enemy.death_flags = death_flags
 
 
     @instruction(108)
@@ -521,6 +535,18 @@ class ECLRunner(object):
         self._enemy.touchable = bool(value)
 
 
+    @instruction(120)
+    def set_automatic_orientation(self, flags):
+        #TODO: does it change anything else than the sprite's rotation?
+        self._enemy.automatic_orientation = bool(flags & 1) #TODO: name
+
+
+    @instruction(123)
+    def skip_frames(self, frames):
+        #TODO: is that all?
+        self.frame += self._getval(frames)
+
+
     @instruction(126)
     def set_remaining_lives(self, lives):
         self._enemy.remaining_lives = lives