# HG changeset patch # User Emmanuel Gil Peyrot # Date 1375537744 -7200 # Node ID c9433188ffdb60da5c782708a7d40b2039623a85 # Parent 40d5f3083ebcc8f6dfe756a4477d5648179605e3 Remove AnmWrapper, since ANMs are lists of entries now. diff --git a/anmviewer b/anmviewer --- a/anmviewer +++ b/anmviewer @@ -24,16 +24,16 @@ from pytouhou.resource.loader import Loa from pytouhou.ui.anmrenderer import ANMRenderer -def main(path, data, name, script, sprites, fixed_pipeline): +def main(path, data, name, script, entry, sprites, fixed_pipeline): resource_loader = Loader() resource_loader.scan_archives(os.path.join(path, name) for name in data) window = Window((384, 448), fixed_pipeline=fixed_pipeline, sound=False) # Get out animation - anm_wrapper = resource_loader.get_anm_wrapper(name.split(',')) - anm = ANMRenderer(window, resource_loader, anm_wrapper, script, sprites) - window.set_runner(anm) + anm = resource_loader.get_anm(name) + renderer = ANMRenderer(window, resource_loader, anm[entry], script, sprites) + window.set_runner(renderer) window.run() @@ -43,10 +43,11 @@ parser.add_argument('data', metavar='DAT', default=('CM.DAT', 'ST.DAT'), nargs='*', help='Game’s .DAT data files') parser.add_argument('-p', '--path', metavar='DIRECTORY', default='.', help='Game directory path.') parser.add_argument('--anm', metavar='ANM', required=True, help='Select an ANM') parser.add_argument('--script', metavar='SCRIPT', type=int, default=0, help='First script to play') +parser.add_argument('--entry', metavar='ENTRY', type=int, default=0, help='Entry to display, in multi-entries ANMs.') parser.add_argument('--sprites', action='store_true', default=False, help='Display sprites instead of scripts.') parser.add_argument('--fixed-pipeline', action='store_true', help='Use the fixed pipeline instead of the new programmable one.') args = parser.parse_args() -main(args.path, tuple(args.data), args.anm, args.script, args.sprites, +main(args.path, tuple(args.data), args.anm, args.script, args.entry, args.sprites, args.fixed_pipeline) diff --git a/pytouhou/game/background.py b/pytouhou/game/background.py --- a/pytouhou/game/background.py +++ b/pytouhou/game/background.py @@ -19,9 +19,9 @@ from pytouhou.game.sprite import Sprite class Background(object): - def __init__(self, stage, anm_wrapper): + def __init__(self, stage, anm): self.stage = stage - self.anm_wrapper = anm_wrapper + self.anm = anm self.last_frame = -1 self.models = [] @@ -53,7 +53,7 @@ class Background(object): quads = [] for script_index, ox, oy, oz, width_override, height_override in obj.quads: sprite = Sprite(width_override, height_override) - anm_runner = ANMRunner(self.anm_wrapper, script_index, sprite) + anm_runner = ANMRunner(self.anm, script_index, sprite) anm_runner.run_frame() quads.append((ox, oy, oz, width_override, height_override, sprite)) self.anm_runners.append(anm_runner) diff --git a/pytouhou/game/bullet.pyx b/pytouhou/game/bullet.pyx --- a/pytouhou/game/bullet.pyx +++ b/pytouhou/game/bullet.pyx @@ -79,7 +79,7 @@ cdef class Bullet(object): launch_mult = bullet_type.launch_anim_penalties[2] self.dx, self.dy = self.dx * launch_mult, self.dy * launch_mult self.sprite = Sprite() - self.anmrunner = ANMRunner(bullet_type.anm_wrapper, + self.anmrunner = ANMRunner(bullet_type.anm, index, self.sprite, bullet_type.launch_anim_offsets[sprite_idx_offset]) self.anmrunner.run_frame() @@ -117,7 +117,7 @@ cdef class Bullet(object): self.sprite.angle = self.angle - pi else: self.sprite.angle = self.angle - self.anmrunner = ANMRunner(bt.anm_wrapper, bt.anim_index, + self.anmrunner = ANMRunner(bt.anm, bt.anim_index, self.sprite, self.sprite_idx_offset) self.anmrunner.run_frame() @@ -146,7 +146,7 @@ cdef class Bullet(object): self.sprite.angle = self.angle - pi else: self.sprite.angle = self.angle - self.anmrunner = ANMRunner(bt.anm_wrapper, bt.cancel_anim_index, + self.anmrunner = ANMRunner(bt.anm, bt.cancel_anim_index, self.sprite, bt.launch_anim_offsets[self.sprite_idx_offset]) self.anmrunner.run_frame() self.dx, self.dy = self.dx / 2., self.dy / 2. diff --git a/pytouhou/game/bullettype.py b/pytouhou/game/bullettype.py --- a/pytouhou/game/bullettype.py +++ b/pytouhou/game/bullettype.py @@ -1,12 +1,12 @@ class BulletType(object): - def __init__(self, anm_wrapper, anim_index, cancel_anim_index, + def __init__(self, anm, anim_index, cancel_anim_index, launch_anim2_index, launch_anim4_index, launch_anim8_index, hitbox_size, launch_anim_penalties=(0.5, 0.4, 1./3.), launch_anim_offsets=(0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 0), type_id=0): self.type_id = type_id - self.anm_wrapper = anm_wrapper + self.anm = anm self.anim_index = anim_index self.cancel_anim_index = cancel_anim_index self.launch_anim2_index = launch_anim2_index diff --git a/pytouhou/game/effect.py b/pytouhou/game/effect.py --- a/pytouhou/game/effect.py +++ b/pytouhou/game/effect.py @@ -20,9 +20,9 @@ from pytouhou.utils.interpolator import class Effect(object): - def __init__(self, pos, index, anm_wrapper): + def __init__(self, pos, index, anm): self.sprite = Sprite() - self.anmrunner = ANMRunner(anm_wrapper, index, self.sprite) + self.anmrunner = ANMRunner(anm, index, self.sprite) self.anmrunner.run_frame() self.removed = False self.objects = [self] @@ -42,8 +42,8 @@ class Effect(object): class Particle(Effect): - def __init__(self, pos, index, anm_wrapper, amp, game, reverse=False, duration=24): - Effect.__init__(self, pos, index, anm_wrapper) + def __init__(self, pos, index, anm, amp, game, reverse=False, duration=24): + Effect.__init__(self, pos, index, anm) self.frame = 0 self.duration = duration diff --git a/pytouhou/game/enemy.py b/pytouhou/game/enemy.py --- a/pytouhou/game/enemy.py +++ b/pytouhou/game/enemy.py @@ -24,9 +24,9 @@ from pytouhou.game.bullet import LAUNCHE class Enemy(object): - def __init__(self, pos, life, _type, bonus_dropped, die_score, anm_wrapper, game): + def __init__(self, pos, life, _type, bonus_dropped, die_score, anms, game): self._game = game - self._anm_wrapper = anm_wrapper + self._anms = anms self._type = _type self.process = None @@ -221,8 +221,9 @@ class Enemy(object): def set_anim(self, index): + entry = 0 if index in self._anms[0].scripts else 1 self.sprite = Sprite() - self.anmrunner = ANMRunner(self._anm_wrapper, index, self.sprite) + self.anmrunner = ANMRunner(self._anms[entry], index, self.sprite) self.anmrunner.run_frame() @@ -241,8 +242,9 @@ class Enemy(object): self._game.new_particle((self.x, self.y), color, 256) #TODO: find the real size. - def set_aux_anm(self, number, script): - self.aux_anm[number] = Effect((self.x, self.y), script, self._anm_wrapper) + def set_aux_anm(self, number, index): + entry = 0 if index in self._anms[0].scripts else 1 + self.aux_anm[number] = Effect((self.x, self.y), index, self._anms[entry]) def set_pos(self, x, y, z): diff --git a/pytouhou/game/face.py b/pytouhou/game/face.py --- a/pytouhou/game/face.py +++ b/pytouhou/game/face.py @@ -18,12 +18,12 @@ from pytouhou.vm.anmrunner import ANMRun class Face(object): - __slots__ = ('_anm_wrapper', 'sprite', 'anmrunner', 'side', 'x', 'y', 'objects') + __slots__ = ('_anms', 'sprite', 'anmrunner', 'side', 'x', 'y', 'objects') - def __init__(self, anm_wrapper, effect, side): - self._anm_wrapper = anm_wrapper + def __init__(self, anms, effect, side): + self._anms = anms self.sprite = Sprite() - self.anmrunner = ANMRunner(anm_wrapper, side * 2, self.sprite) + self.anmrunner = ANMRunner(self._anms[0][0][0], side * 2, self.sprite) self.side = side self.load(0) self.animate(effect) @@ -40,10 +40,9 @@ class Face(object): def load(self, index): - self.sprite.anm, self.sprite.texcoords = self._anm_wrapper.get_sprite(self.side * 8 + index) + self.sprite.anm, self.sprite.texcoords = self._anms[self.side][index] self.anmrunner.run_frame() def update(self): self.anmrunner.run_frame() - diff --git a/pytouhou/game/game.py b/pytouhou/game/game.py --- a/pytouhou/game/game.py +++ b/pytouhou/game/game.py @@ -105,7 +105,7 @@ class Game(object): def enable_spellcard_effect(self): self.spellcard_effect = Effect((-32., -16.), 0, - self.spellcard_effect_anm_wrapper) #TODO: find why this offset is necessary. + self.spellcard_effect_anm) #TODO: find why this offset is necessary. self.spellcard_effect.sprite.allow_dest_offset = True #TODO: should be the role of anm’s 25th instruction. Investigate! @@ -174,20 +174,20 @@ class Game(object): enemy.death_callback = -1 - def new_effect(self, pos, anim, anm_wrapper=None, number=1): + def new_effect(self, pos, anim, anm=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.etama)) + self.effects.append(Effect(pos, anim, anm or self.etama[1])) 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.etama, amp, self, reverse=reverse, duration=duration)) + self.effects.append(Particle(pos, anim, self.etama[1], amp, self, reverse=reverse, duration=duration)) def new_enemy(self, pos, life, instr_type, bonus_dropped, die_score): - enemy = Enemy(pos, life, instr_type, bonus_dropped, die_score, self.enm_anm_wrapper, self) + enemy = Enemy(pos, life, instr_type, bonus_dropped, die_score, self.enm_anm, self) self.enemies.append(enemy) return enemy @@ -198,7 +198,7 @@ class Game(object): def new_label(self, pos, text): - label = Text(pos, self.interface.ascii_wrapper, text=text, xspacing=8, shift=48) + label = Text(pos, self.interface.ascii_anm, text=text, xspacing=8, shift=48) label.set_timeout(60, effect='move') self.labels.append(label) return label @@ -209,7 +209,7 @@ class Game(object): #TODO: Scale pos = pos[0] + 192, pos[1] - label = Text(pos, self.interface.ascii_wrapper, text=hint['Text'], align=hint['Align']) + label = Text(pos, self.interface.ascii_anm, text=hint['Text'], align=hint['Align']) label.set_timeout(hint['Time']) label.set_alpha(hint['Alpha']) label.set_color(hint['Color'], text=False) @@ -218,7 +218,7 @@ class Game(object): def new_face(self, side, effect): - face = Face(self.msg_anm_wrapper, effect, side) + face = Face(self.msg_anm, effect, side) self.faces[side] = face return face diff --git a/pytouhou/game/itemtype.py b/pytouhou/game/itemtype.py --- a/pytouhou/game/itemtype.py +++ b/pytouhou/game/itemtype.py @@ -1,9 +1,11 @@ from pytouhou.game.sprite import Sprite class ItemType(object): - def __init__(self, anm_wrapper, sprite_index, indicator_sprite_index): - self.anm_wrapper = anm_wrapper + def __init__(self, anm, sprite_index, indicator_sprite_index): + self.anm = anm self.sprite = Sprite() - self.sprite.anm, self.sprite.texcoords = anm_wrapper.get_sprite(sprite_index) + self.sprite.anm = anm + self.sprite.texcoords = anm.sprites[sprite_index] self.indicator_sprite = Sprite() - self.indicator_sprite.anm, self.indicator_sprite.texcoords = anm_wrapper.get_sprite(indicator_sprite_index) + self.indicator_sprite.anm = anm + self.indicator_sprite.texcoords = anm.sprites[indicator_sprite_index] diff --git a/pytouhou/game/laser.py b/pytouhou/game/laser.py --- a/pytouhou/game/laser.py +++ b/pytouhou/game/laser.py @@ -22,10 +22,11 @@ STARTING, STARTED, STOPPING = range(3) class LaserLaunchAnim(object): - def __init__(self, laser, anm_wrapper, index): + def __init__(self, laser, anm, index): self._laser = laser self.sprite = Sprite() - self.sprite.anm, self.sprite.texcoords = anm_wrapper.get_sprite(index) + self.sprite.anm = anm + self.sprite.texcoords = anm.sprites[index] self.sprite.blendfunc = 1 self.removed = False self.objects = [self] @@ -57,7 +58,7 @@ class Laser(object): grazing_delay, grazing_extra_duration, game): self._game = game - launch_anim = LaserLaunchAnim(self, laser_type.anm_wrapper, + launch_anim = LaserLaunchAnim(self, laser_type.anm, laser_type.launch_anim_offsets[sprite_idx_offset] + laser_type.launch_sprite_idx) self._game.effects.append(launch_anim) @@ -97,7 +98,7 @@ class Laser(object): lt = self._laser_type self.sprite = Sprite() self.sprite.angle = self.angle - self.anmrunner = ANMRunner(lt.anm_wrapper, lt.anim_index, + self.anmrunner = ANMRunner(lt.anm, lt.anim_index, self.sprite, self.sprite_idx_offset) self.anmrunner.run_frame() @@ -234,7 +235,7 @@ class PlayerLaser(object): lt = self._laser_type self.sprite = Sprite() - self.anmrunner = ANMRunner(lt.anm_wrapper, lt.anim_index, + self.anmrunner = ANMRunner(lt.anm, lt.anim_index, self.sprite, self.sprite_idx_offset) #self.sprite.blendfunc = 1 #XXX self.anmrunner.run_frame() diff --git a/pytouhou/game/lasertype.py b/pytouhou/game/lasertype.py --- a/pytouhou/game/lasertype.py +++ b/pytouhou/game/lasertype.py @@ -1,8 +1,8 @@ class LaserType(object): - def __init__(self, anm_wrapper, anim_index, + def __init__(self, anm, anim_index, launch_sprite_idx=140, launch_anim_offsets=(0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 0)): - self.anm_wrapper = anm_wrapper + self.anm = anm self.anim_index = anim_index self.launch_sprite_idx = launch_sprite_idx self.launch_anim_offsets = launch_anim_offsets diff --git a/pytouhou/game/orb.py b/pytouhou/game/orb.py --- a/pytouhou/game/orb.py +++ b/pytouhou/game/orb.py @@ -21,9 +21,9 @@ class Orb(object): __slots__ = ('sprite', 'anmrunner', 'offset_x', 'offset_y', 'player_state', 'fire') - def __init__(self, anm_wrapper, index, player_state, fire_func): + def __init__(self, anm, index, player_state, fire_func): self.sprite = Sprite() - self.anmrunner = ANMRunner(anm_wrapper, index, self.sprite) + self.anmrunner = ANMRunner(anm, index, self.sprite) self.anmrunner.run_frame() self.offset_x = 0 diff --git a/pytouhou/game/player.py b/pytouhou/game/player.py --- a/pytouhou/game/player.py +++ b/pytouhou/game/player.py @@ -53,11 +53,11 @@ class PlayerState(object): class Player(object): - def __init__(self, state, game, anm_wrapper): + def __init__(self, state, game, anm): self._game = game self.sprite = None self.anmrunner = None - self.anm_wrapper = anm_wrapper + self.anm = anm self.speeds = (self.sht.horizontal_vertical_speed, self.sht.diagonal_speed, @@ -86,7 +86,7 @@ class Player(object): def set_anim(self, index): self.sprite = Sprite() - self.anmrunner = ANMRunner(self.anm_wrapper, index, self.sprite) + self.anmrunner = ANMRunner(self.anm, index, self.sprite) self.anmrunner.run_frame() @@ -134,7 +134,7 @@ class Player(object): if lasers[number]: continue - laser_type = LaserType(self.anm_wrapper, shot.sprite % 256, 68) + laser_type = LaserType(self.anm, shot.sprite % 256, 68) lasers[number] = PlayerLaser(laser_type, 0, shot.hitbox, shot.damage, shot.angle, shot.speed, shot.interval, origin) continue @@ -148,7 +148,7 @@ class Player(object): y = origin.y + shot.pos[1] #TODO: find a better way to do that. - bullet_type = BulletType(self.anm_wrapper, shot.sprite % 256, + bullet_type = BulletType(self.anm, shot.sprite % 256, shot.sprite % 256 + 32, #TODO: find the real cancel anim 0, 0, 0, 0.) #TODO: Type 1 (homing bullets) @@ -274,7 +274,7 @@ class Player(object): self.direction = None self.sprite = Sprite() - self.anmrunner = ANMRunner(self.anm_wrapper, 0, self.sprite) + self.anmrunner = ANMRunner(self.anm, 0, self.sprite) self.sprite.alpha = 128 self.sprite.rescale = 0.0, 2.5 self.sprite.fade(30, 255, lambda x: x) diff --git a/pytouhou/game/text.py b/pytouhou/game/text.py --- a/pytouhou/game/text.py +++ b/pytouhou/game/text.py @@ -28,7 +28,7 @@ class Glyph(object): class Widget(object): - def __init__(self, pos, back_wrapper=None, back_script=22): + def __init__(self, pos, back_anm=None, back_script=22): self.sprite = None self.removed = False self.changed = True @@ -36,10 +36,10 @@ class Widget(object): self.frame = 0 # Set up the backround sprite - self.back_wrapper = back_wrapper - if back_wrapper: + self.back_anm = back_anm + if back_anm: self.sprite = Sprite() - self.anmrunner = ANMRunner(back_wrapper, back_script, self.sprite) + self.anmrunner = ANMRunner(back_anm, back_script, self.sprite) self.anmrunner.run_frame() self.x, self.y = pos @@ -54,17 +54,17 @@ class Widget(object): class GlyphCollection(Widget): - def __init__(self, pos, anm_wrapper, back_wrapper=None, ref_script=0, + def __init__(self, pos, anm, back_anm=None, ref_script=0, xspacing=14, back_script=22): - Widget.__init__(self, pos, back_wrapper, back_script) + Widget.__init__(self, pos, back_anm, back_script) self.ref_sprite = Sprite() - self.anm_wrapper = anm_wrapper + self.anm = anm self.glyphes = [] self.xspacing = xspacing # Set up ref sprite - anm_runner = ANMRunner(anm_wrapper, ref_script, self.ref_sprite) + anm_runner = ANMRunner(anm, ref_script, self.ref_sprite) anm_runner.run_frame() self.ref_sprite.corner_relative_placement = True #TODO: perhaps not right @@ -82,7 +82,8 @@ class GlyphCollection(Widget): def set_sprites(self, sprite_indexes): self.set_length(len(sprite_indexes)) for glyph, idx in zip(self.glyphes, sprite_indexes): - glyph.sprite.anm, glyph.sprite.texcoords = self.anm_wrapper.get_sprite(idx) + glyph.sprite.anm = self.anm + glyph.sprite.texcoords = self.anm.sprites[idx] glyph.sprite.changed = True @@ -105,9 +106,9 @@ class GlyphCollection(Widget): class Text(GlyphCollection): - def __init__(self, pos, ascii_wrapper, back_wrapper=None, text='', + def __init__(self, pos, ascii_anm, back_anm=None, text='', xspacing=14, shift=21, back_script=22, align='left'): - GlyphCollection.__init__(self, pos, ascii_wrapper, back_wrapper, + GlyphCollection.__init__(self, pos, ascii_anm, back_anm, xspacing=xspacing, back_script=back_script) self.text = '' self.shift = shift @@ -193,10 +194,10 @@ class Text(GlyphCollection): class Counter(GlyphCollection): - def __init__(self, pos, anm_wrapper, back_wrapper=None, script=0, + def __init__(self, pos, anm, back_anm=None, script=0, xspacing=16, value=0, back_script=22): - GlyphCollection.__init__(self, pos, anm_wrapper, - back_wrapper=back_wrapper, ref_script=script, + GlyphCollection.__init__(self, pos, anm, + back_anm=back_anm, ref_script=script, xspacing=xspacing, back_script=back_script) self.value = value @@ -221,9 +222,9 @@ class Counter(GlyphCollection): class Gauge(object): - def __init__(self, pos, anm_wrapper, max_length=280, maximum=1, value=0): + def __init__(self, pos, anm, max_length=280, maximum=1, value=0): self.sprite = Sprite() - self.anmrunner = ANMRunner(anm_wrapper, 21, self.sprite) + self.anmrunner = ANMRunner(anm, 21, self.sprite) self.anmrunner.run_frame() self.removed = False self.sprite.corner_relative_placement = True #TODO: perhaps not right diff --git a/pytouhou/games/eosd.py b/pytouhou/games/eosd.py --- a/pytouhou/games/eosd.py +++ b/pytouhou/games/eosd.py @@ -34,52 +34,54 @@ class EoSDGame(Game): continues=0, hints=None): if not bullet_types: - etama3 = resource_loader.get_anm_wrapper(('etama3.anm',)) - self.etama = resource_loader.get_anm_wrapper(('etama4.anm',)) - bullet_types = [BulletType(etama3, 0, 11, 14, 15, 16, hitbox_size=2, + self.etama = resource_loader.get_multi_anm(('etama3.anm', 'etama4.anm')) + bullet_types = [BulletType(self.etama[0], 0, 11, 14, 15, 16, hitbox_size=2, type_id=0), - BulletType(etama3, 1, 12, 17, 18, 19, hitbox_size=3, + BulletType(self.etama[0], 1, 12, 17, 18, 19, hitbox_size=3, type_id=1), - BulletType(etama3, 2, 12, 17, 18, 19, hitbox_size=2, + BulletType(self.etama[0], 2, 12, 17, 18, 19, hitbox_size=2, type_id=2), - BulletType(etama3, 3, 12, 17, 18, 19, hitbox_size=3, + BulletType(self.etama[0], 3, 12, 17, 18, 19, hitbox_size=3, type_id=3), - BulletType(etama3, 4, 12, 17, 18, 19, hitbox_size=2.5, + BulletType(self.etama[0], 4, 12, 17, 18, 19, hitbox_size=2.5, type_id=4), - BulletType(etama3, 5, 12, 17, 18, 19, hitbox_size=2, + BulletType(self.etama[0], 5, 12, 17, 18, 19, hitbox_size=2, type_id=5), - BulletType(etama3, 6, 13, 20, 20, 20, hitbox_size=8, + BulletType(self.etama[0], 6, 13, 20, 20, 20, hitbox_size=8, launch_anim_offsets=(0, 1, 1, 2, 2, 3, 4, 0), type_id=6), - BulletType(etama3, 7, 13, 20, 20, 20, hitbox_size=5.5, + BulletType(self.etama[0], 7, 13, 20, 20, 20, hitbox_size=5.5, launch_anim_offsets=(1,)*28, type_id=7), - BulletType(etama3, 8, 13, 20, 20, 20, hitbox_size=4.5, + BulletType(self.etama[0], 8, 13, 20, 20, 20, hitbox_size=4.5, launch_anim_offsets=(0, 1, 1, 2, 2, 3, 4, 0), type_id=8), - BulletType(self.etama, 0, 1, 2, 2, 2, hitbox_size=16, + BulletType(self.etama[1], 0, 1, 2, 2, 2, hitbox_size=16, launch_anim_offsets=(0, 1, 2, 3, 4, 5, 6, 7, 8), type_id=9)] if not laser_types: - laser_types = [LaserType(etama3, 9), - LaserType(etama3, 10)] + laser_types = [LaserType(self.etama[0], 9), + LaserType(self.etama[0], 10)] if not item_types: - item_types = [ItemType(etama3, 0, 7), #Power - ItemType(etama3, 1, 8), #Point - ItemType(etama3, 2, 9), #Big power - ItemType(etama3, 3, 10), #Bomb - ItemType(etama3, 4, 11), #Full power - ItemType(etama3, 5, 12), #1up - ItemType(etama3, 6, 13)] #Star + item_types = [ItemType(self.etama[0], 0, 7), #Power + ItemType(self.etama[0], 1, 8), #Point + ItemType(self.etama[0], 2, 9), #Big power + ItemType(self.etama[0], 3, 10), #Bomb + ItemType(self.etama[0], 4, 11), #Full power + ItemType(self.etama[0], 5, 12), #1up + ItemType(self.etama[0], 6, 13)] #Star - self.enm_anm_wrapper = resource_loader.get_anm_wrapper2(('stg%denm.anm' % stage, - 'stg%denm2.anm' % stage)) + try: + self.enm_anm = resource_loader.get_multi_anm(('stg%denm.anm' % stage, + 'stg%denm2.anm' % stage)) + except KeyError: + self.enm_anm = resource_loader.get_anm('stg%denm.anm' % stage) ecl = resource_loader.get_ecl('ecldata%d.ecl' % stage) self.ecl_runners = [ECLMainRunner(main, ecl.subs, self) for main in ecl.mains] - self.spellcard_effect_anm_wrapper = resource_loader.get_anm_wrapper(('eff0%d.anm' % stage,)) + self.spellcard_effect_anm = resource_loader.get_single_anm('eff0%d.anm' % stage) player_face = player_states[0].character // 2 enemy_face = [('face03a.anm', 'face03b.anm'), @@ -90,11 +92,16 @@ class EoSDGame(Game): ('face09b.anm', 'face10a.anm', 'face10b.anm'), ('face08a.anm', 'face12a.anm', 'face12b.anm', 'face12c.anm')] self.msg = resource_loader.get_msg('msg%d.dat' % stage) - self.msg_anm_wrapper = resource_loader.get_anm_wrapper2(('face0%da.anm' % player_face, - 'face0%db.anm' % player_face, - 'face0%dc.anm' % player_face) - + enemy_face[stage - 1], - (0, 2, 4, 8, 10, 11, 12)) + msg_anm = [resource_loader.get_multi_anm(('face0%da.anm' % player_face, + 'face0%db.anm' % player_face, + 'face0%dc.anm' % player_face)), + resource_loader.get_multi_anm(enemy_face[stage - 1])] + + self.msg_anm = [[], []] + for i, anms in enumerate(msg_anm): + for anm in anms: + for sprite in anm.sprites.values(): + self.msg_anm[i].append((anm, sprite)) characters = resource_loader.get_eosd_characters() players = [EoSDPlayer(state, self, resource_loader, characters[state.character]) for state in player_states] @@ -105,8 +112,8 @@ class EoSDGame(Game): # Load stage data self.std = resource_loader.get_stage('stage%d.std' % stage) - background_anm_wrapper = resource_loader.get_anm_wrapper(('stg%dbg.anm' % stage,)) - self.background = Background(self.std, background_anm_wrapper) + background_anm = resource_loader.get_single_anm('stg%dbg.anm' % stage) + self.background = Background(self.std, background_anm) self.resource_loader = resource_loader #XXX: currently used for texture preload in pytouhou.ui.gamerunner. Wipe it! @@ -119,8 +126,8 @@ class EoSDGame(Game): class EoSDInterface(object): def __init__(self, game, resource_loader): self.game = game - front = resource_loader.get_anm_wrapper(('front.anm',)) - self.ascii_wrapper = resource_loader.get_anm_wrapper(('ascii.anm',)) + front = resource_loader.get_single_anm('front.anm') + self.ascii_anm = resource_loader.get_single_anm('ascii.anm') self.width = 640 self.height = 480 @@ -136,25 +143,25 @@ class EoSDInterface(object): for item in self.items: item.sprite.allow_dest_offset = True #XXX - self.level_start = [Text((176, 200), self.ascii_wrapper, text='STAGE %d' % game.stage)] #TODO: find the exact location. + self.level_start = [Text((176, 200), self.ascii_anm, text='STAGE %d' % game.stage)] #TODO: find the exact location. self.level_start[0].set_timeout(240, effect='fadeout', duration=60, start=120) self.level_start[0].set_color('yellow') #TODO: use the system text for the stage name, and the song name. self.labels = { - 'highscore': Text((500, 58), self.ascii_wrapper, front, text='0'), - 'score': Text((500, 82), self.ascii_wrapper, front, text='0'), + 'highscore': Text((500, 58), self.ascii_anm, front, text='0'), + 'score': Text((500, 82), self.ascii_anm, front, text='0'), 'player': Counter((500, 122), front, front, script=16, value=0), 'bombs': Counter((500, 146), front, front, script=17, value=0), - 'power': Text((500, 186), self.ascii_wrapper, front, text='0'), - 'graze': Text((500, 206), self.ascii_wrapper, front, text='0'), - 'points': Text((500, 226), self.ascii_wrapper, front, text='0'), - 'framerate': Text((512, 464), self.ascii_wrapper, front), - 'debug?': Text((0, 464), self.ascii_wrapper, front), + 'power': Text((500, 186), self.ascii_anm, front, text='0'), + 'graze': Text((500, 206), self.ascii_anm, front, text='0'), + 'points': Text((500, 226), self.ascii_anm, front, text='0'), + 'framerate': Text((512, 464), self.ascii_anm, front), + 'debug?': Text((0, 464), self.ascii_anm, front), # Only when there is a boss. - 'boss_lives': Text((80, 16), self.ascii_wrapper), - 'timeout': Text((384, 16), self.ascii_wrapper), + 'boss_lives': Text((80, 16), self.ascii_anm), + 'timeout': Text((384, 16), self.ascii_anm), } self.labels['boss_lives'].set_color('yellow') @@ -237,13 +244,12 @@ class EoSDPlayer(Player): def __init__(self, state, game, resource_loader, character): self.sht = character[0] self.focused_sht = character[1] - anm_wrapper = resource_loader.get_anm_wrapper(('player0%d.anm' % (state.character // 2),)) - self.anm_wrapper = anm_wrapper + self.anm = resource_loader.get_single_anm('player0%d.anm' % (state.character // 2)) - Player.__init__(self, state, game, anm_wrapper) + Player.__init__(self, state, game, self.anm) - self.orbs = [Orb(self.anm_wrapper, 128, self.state, None), - Orb(self.anm_wrapper, 129, self.state, None)] + self.orbs = [Orb(self.anm, 128, self.state, None), + Orb(self.anm, 129, self.state, None)] self.orbs[0].offset_x = -24 self.orbs[1].offset_x = 24 diff --git a/pytouhou/resource/anmwrapper.py b/pytouhou/resource/anmwrapper.py deleted file mode 100644 --- a/pytouhou/resource/anmwrapper.py +++ /dev/null @@ -1,48 +0,0 @@ -# -*- encoding: utf-8 -*- -## -## Copyright (C) 2012 Thibaut Girka -## -## This program is free software; you can redistribute it and/or modify -## it under the terms of the GNU General Public License as published -## by the Free Software Foundation; version 3 only. -## -## This program is distributed in the hope that it will be useful, -## but WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -## GNU General Public License for more details. -## - -from itertools import repeat, chain - - -class AnmWrapper(object): - def __init__(self, anm_files, offsets=None): - """Wrapper for scripts and sprites described in “anm_files”. - - The optional “offsets” argument specifies a list of offsets to be added - to script and sprite numbers of each file described in “anm_files”. - - That is, if anm_files[0] and anm_files[1] each have only one sprite, - numbered 0 in both cases, and offsets=(0, 1), the first file's sprite - will be numbered 0 and the second file's will be numbered 1. - """ - self.scripts = {} - self.sprites = {} - - if not offsets: - offsets = repeat(0) # “offsets” defaults to zeroes - - for anm, offset in zip(chain(*anm_files), offsets): - for script_id, script in anm.scripts.iteritems(): - self.scripts[script_id + offset] = (anm, script) #TODO: check - for sprite_id, sprite in anm.sprites.iteritems(): - self.sprites[sprite_id + offset] = (anm, sprite) - - - def get_sprite(self, sprite_index): - return self.sprites[sprite_index] - - - def get_script(self, script_index): - return self.scripts[script_index] - diff --git a/pytouhou/resource/loader.py b/pytouhou/resource/loader.py --- a/pytouhou/resource/loader.py +++ b/pytouhou/resource/loader.py @@ -28,9 +28,6 @@ from pytouhou.formats.exe import SHT as from pytouhou.formats.music import Track from pytouhou.formats.fmt import FMT - -from pytouhou.resource.anmwrapper import AnmWrapper - from pytouhou.utils.helpers import get_logger logger = get_logger(__name__) @@ -188,28 +185,13 @@ class Loader(object): return FMT.read(file) #TODO: modular - def get_anm_wrapper(self, names, offsets=None): - """Create an AnmWrapper for ANM files “names”. - - If one of the files “names” does not exist or is not a valid ANM file, - raises an exception. - """ - return AnmWrapper((self.get_anm(name) for name in names), offsets) + def get_single_anm(self, name): + """Hack for EoSD, since it doesn’t support multi-entries ANMs.""" + anm = self.get_anm(name) + assert len(anm) == 1 + return anm[0] - def get_anm_wrapper2(self, names, offsets=None): - """Create an AnmWrapper for ANM files “names”. - - Stop at the first non-existent or invalid ANM file if there is one, - and return an AnmWrapper for all the previous correct files. - """ - anms = [] - - try: - for name in names: - anms.append(self.get_anm(name)) - except KeyError: - pass - - return AnmWrapper(anms, offsets) - + def get_multi_anm(self, names): + """Hack for EoSD, since it doesn’t support multi-entries ANMs.""" + return sum((self.get_anm(name) for name in names), []) diff --git a/pytouhou/ui/anmrenderer.pyx b/pytouhou/ui/anmrenderer.pyx --- a/pytouhou/ui/anmrenderer.pyx +++ b/pytouhou/ui/anmrenderer.pyx @@ -31,7 +31,7 @@ logger = get_logger(__name__) class ANMRenderer(Renderer): - def __init__(self, window, resource_loader, anm_wrapper, index=0, sprites=False): + def __init__(self, window, resource_loader, anm, index=0, sprites=False): self.use_fixed_pipeline = window.use_fixed_pipeline #XXX Renderer.__init__(self, resource_loader) @@ -39,7 +39,7 @@ class ANMRenderer(Renderer): self.window = window self.texture_manager.load(resource_loader.instanced_anms.values()) - self._anm_wrapper = anm_wrapper + self._anm = anm self.sprites = sprites self.clear_color = (0., 0., 0., 1.) self.force_allow_dest_offset = False @@ -74,10 +74,11 @@ class ANMRenderer(Renderer): index = self.num self.sprite = Sprite() if self.sprites: - self.sprite.anm, self.sprite.texcoords = self._anm_wrapper.get_sprite(index) + self.sprite.anm = self._anm + self.sprite.texcoords = self._anm.sprites[index] print('Loaded sprite %d' % index) else: - self.anmrunner = ANMRunner(self._anm_wrapper, index, self.sprite) + self.anmrunner = ANMRunner(self._anm, index, self.sprite) print('Loading anim %d, handled events: %r' % (index, self.anmrunner.script.interrupts.keys())) self.num = index @@ -93,9 +94,9 @@ class ANMRenderer(Renderer): def index_items(self): self.items = {} if self.sprites: - self.items = self._anm_wrapper.sprites + self.items = self._anm.sprites else: - self.items = self._anm_wrapper.scripts + self.items = self._anm.scripts def toggle_sprites(self): diff --git a/pytouhou/vm/anmrunner.py b/pytouhou/vm/anmrunner.py --- a/pytouhou/vm/anmrunner.py +++ b/pytouhou/vm/anmrunner.py @@ -23,9 +23,9 @@ logger = get_logger(__name__) class ANMRunner(object): __metaclass__ = MetaRegistry - __slots__ = ('_anm_wrapper', '_sprite', 'running', - 'sprite_index_offset', 'script', 'instruction_pointer', - 'frame', 'waiting', 'handlers', 'variables', 'version', 'timeout') + __slots__ = ('_anm', '_sprite', 'running', 'sprite_index_offset', 'script', + 'instruction_pointer', 'frame', 'waiting', 'handlers', + 'variables', 'version', 'timeout') #TODO: check! formulae = {0: lambda x: x, @@ -38,13 +38,13 @@ class ANMRunner(object): 7: lambda x: x, 255: lambda x: x} #XXX - def __init__(self, anm_wrapper, script_id, sprite, sprite_index_offset=0): - self._anm_wrapper = anm_wrapper + def __init__(self, anm, script_id, sprite, sprite_index_offset=0): + self._anm = anm self._sprite = sprite self.running = True self.waiting = False - anm, self.script = anm_wrapper.get_script(script_id) + self.script = anm.scripts[script_id] self.version = anm.version self.handlers = self._handlers[{0: 6, 2: 7}[anm.version]] self.frame = 0 @@ -166,7 +166,7 @@ class ANMRunner(object): @instruction(3, 7) def load_sprite(self, sprite_index): #TODO: version 2 only: do not crash when assigning a non-existant sprite. - self._sprite.anm, self._sprite.texcoords = self._anm_wrapper.get_sprite(sprite_index + self.sprite_index_offset) + self._sprite.anm, self._sprite.texcoords = self._anm, self._anm.sprites[sprite_index + self.sprite_index_offset] @instruction(2) diff --git a/pytouhou/vm/eclrunner.py b/pytouhou/vm/eclrunner.py --- a/pytouhou/vm/eclrunner.py +++ b/pytouhou/vm/eclrunner.py @@ -920,7 +920,7 @@ class ECLRunner(object): elif 4 <= anim <= 15: self._game.new_particle((self._enemy.x, self._enemy.y), anim + 5, 192, number=number) elif anim == 16: - self._game.new_effect((self._enemy.x, self._enemy.y), 0, self._game.spellcard_effect_anm_wrapper, number=number) + self._game.new_effect((self._enemy.x, self._enemy.y), 0, self._game.spellcard_effect_anm, number=number) elif anim == 17: self._game.new_particle((self._enemy.x, self._enemy.y), anim - 10, 640, number=number, reverse=True, duration=60) elif anim == 18: