# HG changeset patch # User Thibaut Girka # Date 1314470536 -7200 # Node ID a03d7a94b9974e96f7af599fc083e384a2dc6366 # Parent 7c1f20407b3e9a2f0d8db03c68343d355f5e1467 Add support for a few ANM instructions diff --git a/pytouhou/formats/anm0.py b/pytouhou/formats/anm0.py --- a/pytouhou/formats/anm0.py +++ b/pytouhou/formats/anm0.py @@ -33,12 +33,24 @@ class Animations(object): 10: ('fff', 'set_3d_rotations_speed'), 11: ('ff', 'set_scale_speed'), 12: ('ii', 'fade'), + 13: ('', None), + 14: ('', None), 15: ('', 'keep_still'), 16: ('i', 'set_random_sprite'), + 17: ('fff', None), + 18: ('ffii', None), + 19: ('ffii', None), + 20: ('fffi', None), + 21: ('', None), + 22: ('i', None), 23: ('', 'set_corner_relative_placement'), + 24: ('', None), + 25: ('i', 'set_allow_offset'), #TODO: better name + 26: ('i', None), 27: ('f', 'shift_texture_x'), 28: ('f', 'shift_texture_y'), - 30: ('ffi', 'scale_in')} + 30: ('ffi', 'scale_in'), + 31: ('i', None)} def __init__(self): diff --git a/pytouhou/game/sprite.py b/pytouhou/game/sprite.py --- a/pytouhou/game/sprite.py +++ b/pytouhou/game/sprite.py @@ -14,6 +14,7 @@ from pytouhou.utils.matrix import Matrix +from pytouhou.utils.interpolator import Interpolator class AnmWrapper(object): @@ -42,7 +43,13 @@ class Sprite(object): self._removed = False self._changed = False + self.scale_interpolator = None + self.fade_interpolator = None + self.offset_interpolator = None + self.texcoords = (0, 0, 0, 0) # x, y, width, height + self.dest_offset = (0., 0., 0.) + self.allow_dest_offset = False self.texoffsets = (0., 0.) self.mirrored = False self.rescale = (1., 1.) @@ -58,7 +65,41 @@ class Sprite(object): self._colors = [] + def fade(self, duration, alpha, formula): + if not self.fade_interpolator: + self.fade_interpolator = Interpolator((self.alpha,), formula) + self.fade_interpolator.set_interpolation_start(self.frame, (self.alpha,)) + self.fade_interpolator.set_interpolation_end(self.frame + duration - 1, (alpha,)) + + + def scale_in(self, duration, sx, sy, formula): + if not self.scale_interpolator: + self.scale_interpolator = Interpolator(self.rescale, formula) + self.scale_interpolator.set_interpolation_start(self.frame, self.rescale) + self.scale_interpolator.set_interpolation_end(self.frame + duration - 1, (sx, sy)) + + + def move_in(self, duration, x, y, z, formula): + if not self.offset_interpolator: + self.offset_interpolator = Interpolator(self.dest_offset, formula) + self.offset_interpolator.set_interpolation_start(self.frame, self.dest_offset) + 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): + if self.fade_interpolator: + self.fade_interpolator.update(self.frame) + self.alpha = int(self.fade_interpolator.values[0]) + + if self.scale_interpolator: + self.scale_interpolator.update(self.frame) + self.rescale = self.scale_interpolator.values + + if self.offset_interpolator: + self.offset_interpolator.update(self.frame) + self.dest_offset = self.offset_interpolator.values + + vertmat = Matrix([[-.5, .5, .5, -.5], [-.5, -.5, .5, .5], [ .0, .0, .0, .0], @@ -82,6 +123,8 @@ class Sprite(object): vertmat.rotate_z(-rz) #TODO: minus, really? if self.corner_relative_placement: # Reposition vertmat.translate(width / 2., height / 2., 0.) + if self.allow_dest_offset: + vertmat.translate(*self.dest_offset) x_1 = 1. / self.anm.size[0] y_1 = 1. / self.anm.size[1] @@ -104,4 +147,5 @@ class Sprite(object): self.rotations_3d = ax + sax, ay + say, az + saz self.rescale = self.rescale[0] + self.scale_speed[0], self.rescale[1] + self.scale_speed[1] self._changed = True + self.frame += 1 diff --git a/pytouhou/vm/anmrunner.py b/pytouhou/vm/anmrunner.py --- a/pytouhou/vm/anmrunner.py +++ b/pytouhou/vm/anmrunner.py @@ -118,17 +118,36 @@ class ANMRunner(object): self._sprite.scale_speed = ssx, ssy + @instruction(12) + def fade(self, new_alpha, duration): + self._sprite.fade(duration, new_alpha, lambda x: x) #TODO: formula + + @instruction(15) + @instruction(21) #TODO + def keep_still(self): + self._running = False + @instruction(16) def load_random_sprite(self, min_idx, amp): #TODO: use the game's PRNG? self.load_sprite(min_idx + randrange(amp)) + @instruction(19) + def move_in(self, x, y, z, duration): + self._sprite.move_in(duration, x, y, z, lambda x: x) #TODO: formula + + @instruction(23) def set_corner_relative_placement(self): self._sprite.corner_relative_placement = True #TODO + @instruction(25) + def set_allow_dest_offset(self, value): + self._sprite.allow_dest_offset = bool(value) + + @instruction(27) def shift_texture_x(self, dx): tox, toy = self._sprite.texoffsets @@ -141,8 +160,7 @@ class ANMRunner(object): self._sprite.texoffsets = tox, toy + dy - @instruction(15) - @instruction(21) #TODO - def keep_still(self): - self._running = False + @instruction(30) + def scale_in(self, sx, sy, duration): + self._sprite.scale_in(duration, sx, sy, lambda x: x) #TODO: formula