Mercurial > nagslang
view nagslang/render.py @ 219:f9e92d540bfa
Less hacky rotation suppression.
author | Jeremy Thurgood <firxen@gmail.com> |
---|---|
date | Wed, 04 Sep 2013 16:21:21 +0200 |
parents | 9e2ef2f15035 |
children | 0c0d5919f70a |
line wrap: on
line source
import math import pygame import pymunk from nagslang.options import options class Renderer(object): def set_game_object(self, game_object): self.game_object = game_object def _render_shape(self, surface): shape = self.game_object.get_shape() # Less general that pymunk.pygame_util.draw, but also a lot less noisy. color = getattr(shape, 'color', pygame.color.THECOLORS['lightblue']) # We only explicitly draw Circle and Poly shapes. Everything else we # forward to pymunk. if isinstance(shape, pymunk.Circle): centre = pymunk.pygame_util.to_pygame(shape.body.position, surface) radius = int(shape.radius) pygame.draw.circle(surface, color, centre, radius, 2) elif isinstance(shape, pymunk.Poly): # polygon bounding box points = [pymunk.pygame_util.to_pygame(p, surface) for p in shape.get_vertices()] pygame.draw.lines(surface, color, True, points, 2) else: pymunk.pygame_util.draw(surface, shape) def render(self, surface): if options.debug: self._render_shape(surface) def animate(self): # Used by time animatations to advance the clock pass def image_pos(image, pos): return (pos[0] - image.get_width() / 2, pos[1] - image.get_height() / 2) class ImageRenderer(Renderer): rotate = True # Set to `False` to suppress image rotation. def __init__(self, image): self._image = image def get_image(self): return self._image def rotate_image(self, image): if not self._rotate: return image angle = self.game_object.get_render_angle() * 180 / math.pi return pygame.transform.rotate(image, angle) def render_image(self, surface, image): image = self.rotate_image(image) pos = self.game_object.get_render_position(surface) surface.blit(image, image_pos(image, pos)) def render(self, surface): self.render_image(surface, self.get_image()) super(ImageRenderer, self).render(surface) class ImageStateRenderer(ImageRenderer): def __init__(self, state_images): self._state_images = state_images def get_image(self): return self._state_images[self.game_object.puzzler.get_state()] 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(): renderer.rotate = False super(FacingSelectionRenderer, self).__init__(renderers) self._face = 'left' def _update_facing(self, angle): if abs(angle) < math.pi / 2: self._face = 'right' elif abs(angle) > math.pi / 2: self._face = 'left' def select_renderer(self): angle = self.game_object.get_render_angle() self._update_facing(angle) return self._face class ShapeRenderer(Renderer): def render(self, surface): self._render_shape(surface) super(ShapeRenderer, self).render(surface) class ShapeStateRenderer(ShapeRenderer): """Renders the shape in a different colour depending on the state. Requires the game object it's attached to to have a puzzler. """ def render(self, surface): if self.game_object.puzzler.get_state(): color = pygame.color.THECOLORS['green'] else: color = pygame.color.THECOLORS['red'] self.game_object.get_shape().color = color super(ShapeStateRenderer, self).render(surface)