# HG changeset patch # User Jeremy Thurgood # Date 1378299217 -7200 # Node ID d98daba73055c9f371bdf3df2572a2d117caefee # Parent f23ab2dd6ce80bbe2ae0762261648f698509333e Composition-based renderers. diff -r f23ab2dd6ce8 -r d98daba73055 nagslang/enemies.py --- a/nagslang/enemies.py Wed Sep 04 13:15:48 2013 +0200 +++ b/nagslang/enemies.py Wed Sep 04 14:53:37 2013 +0200 @@ -54,27 +54,14 @@ self.angle = 0 def _setup_renderer(self): - self.renderer = render.AnimatedFacingImageRenderer( - (self._get_image('alien_A_1.png'), - self._get_image('alien_A_1.png'), - self._get_image('alien_A_1.png'), - self._get_image('alien_A_1.png'), - self._get_image('alien_A_1.png'), - self._get_image('alien_A_1.png'), - self._get_image('alien_A_2.png'), - self._get_image('alien_A_2.png'), - self._get_image('alien_A_2.png')), - (self._get_image('alien_A_1.png', FLIP_H), - self._get_image('alien_A_1.png', FLIP_H), - self._get_image('alien_A_1.png', FLIP_H), - self._get_image('alien_A_1.png', FLIP_H), - self._get_image('alien_A_1.png', FLIP_H), - self._get_image('alien_A_1.png', FLIP_H), - self._get_image('alien_A_2.png', FLIP_H), - self._get_image('alien_A_2.png', FLIP_H), - self._get_image('alien_A_2.png', FLIP_H))) - # We're always animated - self.renderer.start() + self.renderer = render.FacingSelectionRenderer({ + 'left': render.TimedAnimatedRenderer( + [self._get_image('alien_A_1.png'), + self._get_image('alien_A_2.png')], 3), + 'right': render.TimedAnimatedRenderer( + [self._get_image('alien_A_1.png', FLIP_H), + self._get_image('alien_A_2.png', FLIP_H)], 3), + }) def get_render_angle(self): return self.angle diff -r f23ab2dd6ce8 -r d98daba73055 nagslang/game_object.py --- a/nagslang/game_object.py Wed Sep 04 13:15:48 2013 +0200 +++ b/nagslang/game_object.py Wed Sep 04 14:53:37 2013 +0200 @@ -43,6 +43,9 @@ def get_angle(self): return self.get_shape().body.angle + def get_velocity(self): + return self.get_shape().body.velocity + def _get_position(self): return self.get_shape().body.position @@ -146,6 +149,13 @@ def animate(self): self.renderer.animate() + def is_moving(self): + """Returns `True` if this object is moving. + + This is mostly for movement-based animation renderers to look at. + """ + return self.physicser.get_velocity().length > 0 + def collide_with_protagonist(self): """Called as a `pre_solve` collision callback with the protagonist. diff -r f23ab2dd6ce8 -r d98daba73055 nagslang/protagonist.py --- a/nagslang/protagonist.py Wed Sep 04 13:15:48 2013 +0200 +++ b/nagslang/protagonist.py Wed Sep 04 14:53:37 2013 +0200 @@ -81,58 +81,42 @@ def _setup_renderers(self): self.angle = 0 self._renderers = { - self.HUMAN_FORM: render.AnimatedFacingImageRenderer( - (self._get_image('human_1.png'), - self._get_image('human_1.png'), - self._get_image('human_1.png'), - self._get_image('human_2.png'), - self._get_image('human_2.png'), - self._get_image('human_2.png')), - (self._get_image('human_1.png', FLIP_H), - self._get_image('human_1.png', FLIP_H), - self._get_image('human_1.png', FLIP_H), - self._get_image('human_2.png', FLIP_H), - self._get_image('human_2.png', FLIP_H), - self._get_image('human_2.png', FLIP_H))), - self.HUMAN_FORM_BACK: render.AnimatedFacingImageRenderer( - (self._get_image('human_back_1.png'), - self._get_image('human_back_1.png'), - self._get_image('human_back_1.png'), - self._get_image('human_back_2.png'), - self._get_image('human_back_2.png'), - self._get_image('human_back_2.png')), - (self._get_image('human_back_1.png', FLIP_H), - self._get_image('human_back_1.png', FLIP_H), - self._get_image('human_back_1.png', FLIP_H), - self._get_image('human_back_2.png', FLIP_H), - self._get_image('human_back_2.png', FLIP_H), - self._get_image('human_back_2.png', FLIP_H))), - self.WOLF_FORM: render.AnimatedFacingImageRenderer( - (self._get_image('werewolf_1.png'), - self._get_image('werewolf_1.png'), - self._get_image('werewolf_1.png'), - self._get_image('werewolf_2.png'), - self._get_image('werewolf_2.png'), - self._get_image('werewolf_2.png')), - (self._get_image('werewolf_1.png', FLIP_H), - self._get_image('werewolf_1.png', FLIP_H), - self._get_image('werewolf_1.png', FLIP_H), - self._get_image('werewolf_2.png', FLIP_H), - self._get_image('werewolf_2.png', FLIP_H), - self._get_image('werewolf_2.png', FLIP_H))), - self.WOLF_FORM_BACK: render.AnimatedFacingImageRenderer( - (self._get_image('werewolf_back_1.png'), - self._get_image('werewolf_back_1.png'), - self._get_image('werewolf_back_1.png'), - self._get_image('werewolf_back_2.png'), - self._get_image('werewolf_back_2.png'), - self._get_image('werewolf_back_2.png')), - (self._get_image('werewolf_back_1.png', FLIP_H), - self._get_image('werewolf_back_1.png', FLIP_H), - self._get_image('werewolf_back_1.png', FLIP_H), - self._get_image('werewolf_back_2.png', FLIP_H), - self._get_image('werewolf_back_2.png', FLIP_H), - self._get_image('werewolf_back_2.png', FLIP_H))), + self.HUMAN_FORM: render.FacingSelectionRenderer( + { + 'left': render.MovementAnimatedRenderer( + [self._get_image('human_1.png'), + self._get_image('human_2.png')], 3), + 'right': render.MovementAnimatedRenderer( + [self._get_image('human_1.png', FLIP_H), + self._get_image('human_2.png', FLIP_H)], 3), + }), + self.HUMAN_FORM_BACK: render.FacingSelectionRenderer( + { + 'left': render.MovementAnimatedRenderer( + [self._get_image('human_back_1.png'), + self._get_image('human_back_2.png')], 3), + 'right': render.MovementAnimatedRenderer( + [self._get_image('human_back_1.png', FLIP_H), + self._get_image('human_back_2.png', FLIP_H)], 3), + }), + self.WOLF_FORM: render.FacingSelectionRenderer( + { + 'left': render.MovementAnimatedRenderer( + [self._get_image('werewolf_1.png'), + self._get_image('werewolf_2.png')], 3), + 'right': render.MovementAnimatedRenderer( + [self._get_image('werewolf_1.png', FLIP_H), + self._get_image('werewolf_2.png', FLIP_H)], 3), + }), + self.WOLF_FORM_BACK: render.FacingSelectionRenderer( + { + 'left': render.MovementAnimatedRenderer( + [self._get_image('werewolf_back_1.png'), + self._get_image('werewolf_back_2.png')], 3), + 'right': render.MovementAnimatedRenderer( + [self._get_image('werewolf_back_1.png', FLIP_H), + self._get_image('werewolf_back_2.png', FLIP_H)], 3), + }), } for renderer in self._renderers.values(): renderer.set_game_object(self) @@ -190,7 +174,6 @@ def set_direction(self, dx, dy): if (dx, dy) == (0, 0): - self.renderer.stop() return old_angle = self.angle self.angle = pymunk.Vec2d((dx, dy)).angle @@ -205,7 +188,6 @@ self._switch_to_front() self.physicser.apply_impulse( (dx * self.impulse_factor, dy * self.impulse_factor)) - self.renderer.start() def set_position(self, position): self.physicser.position = position @@ -213,6 +195,7 @@ def copy_state(self, old_protagonist): self.physicser.position = old_protagonist.physicser.position self.physicser.switch_form(self.form, old_protagonist.form) + self.impulse_factor = old_protagonist.impulse_factor self.form = old_protagonist.form self.angle = old_protagonist.angle self.render_form = old_protagonist.render_form diff -r f23ab2dd6ce8 -r d98daba73055 nagslang/render.py --- a/nagslang/render.py Wed Sep 04 13:15:48 2013 +0200 +++ b/nagslang/render.py Wed Sep 04 14:53:37 2013 +0200 @@ -71,12 +71,69 @@ return self._state_images[self.game_object.puzzler.get_state()] -class FacingImageRenderer(ImageRenderer): - def __init__(self, left_image, right_image): - self._images = { - 'left': left_image, - 'right': right_image, - } +class TimedAnimatedRenderer(ImageRenderer): + def __init__(self, images, frame_ticks=1): + self._images = images + self._frame_ticks = frame_ticks + self._frame_tick = 0 + self._frame = 0 + + def advance_tick(self): + self._frame_tick += 1 + if self._frame_tick > self._frame_ticks: + self._frame_tick = 0 + self._frame += 1 + if self._frame >= len(self._images): + self._frame = 0 + + def reset(self): + self._frame_tick = 0 + self._frame = 0 + + def get_image(self): + return self._images[self._frame] + + def animate(self): + self.advance_tick() + + +class MovementAnimatedRenderer(TimedAnimatedRenderer): + def animate(self): + if self.game_object.is_moving(): + self.advance_tick() + else: + self.reset() + + +class RendererSelectionRenderer(Renderer): + def __init__(self, renderers): + self._renderers = renderers + + def set_game_object(self, game_object): + self.game_object = game_object + for renderer in self._renderers.values(): + renderer.set_game_object(game_object) + + @property + def renderer(self): + return self._renderers[self.select_renderer()] + + def render(self, surface): + return self.renderer.render(surface) + + def animate(self): + return self.renderer.animate() + + def select_renderer(self): + raise NotImplementedError() + + +class FacingSelectionRenderer(RendererSelectionRenderer): + def __init__(self, renderers): + for renderer in renderers.values(): + # TODO: Unhack this somehow. + renderer.rotate_image = self.rotate_image + super(FacingSelectionRenderer, self).__init__(renderers) self._face = 'left' def _update_facing(self, angle): @@ -89,57 +146,10 @@ # Facing images don't get rotated. return image - def get_facing_image(self): - return self._images[self._face] - - def get_image(self): + def select_renderer(self): angle = self.game_object.get_render_angle() self._update_facing(angle) - return self.get_facing_image() - - -class AnimatedFacingImageRenderer(FacingImageRenderer): - def __init__(self, left_images, right_images): - self._images = { - 'left': left_images, - 'right': right_images, - } - self._frame = 0 - self._moving = False - self._face = 'left' - - def get_facing_image(self): - if self._frame >= len(self._images[self._face]): - self._frame = 0 - return self._images[self._face][self._frame] - - def animate(self): - if self._moving: - self._frame += 1 - else: - self._frame = 0 - - def start(self): - self._moving = True - - def stop(self): - self._moving = False - - -class TimedAnimatedRenderer(ImageRenderer): - - def __init__(self, images): - self._images = images - self._frame = 0 - self._image = None - - def get_image(self): - if self._frame > len(self._imaages): - self._frame = 0 - return self._images[self._frame] - - def animate(self): - self._frame += 1 + return self._face class ShapeRenderer(Renderer):