source: nagslang/render.py@ 218:9e2ef2f15035

Last change on this file since 218:9e2ef2f15035 was 218:9e2ef2f15035, checked in by Jeremy Thurgood <firxen@…>, 8 years ago

Better rendering and movement detection.

File size: 5.0 KB
RevLine 
[207]1import math
2
3import pygame
4import pymunk
5
6from nagslang.options import options
7
8
9class Renderer(object):
10 def set_game_object(self, game_object):
11 self.game_object = game_object
12
13 def _render_shape(self, surface):
14 shape = self.game_object.get_shape()
15 # Less general that pymunk.pygame_util.draw, but also a lot less noisy.
16 color = getattr(shape, 'color', pygame.color.THECOLORS['lightblue'])
17 # We only explicitly draw Circle and Poly shapes. Everything else we
18 # forward to pymunk.
19 if isinstance(shape, pymunk.Circle):
20 centre = pymunk.pygame_util.to_pygame(shape.body.position, surface)
21 radius = int(shape.radius)
22 pygame.draw.circle(surface, color, centre, radius, 2)
23 elif isinstance(shape, pymunk.Poly):
24 # polygon bounding box
25 points = [pymunk.pygame_util.to_pygame(p, surface)
26 for p in shape.get_vertices()]
27 pygame.draw.lines(surface, color, True, points, 2)
28 else:
29 pymunk.pygame_util.draw(surface, shape)
30
31 def render(self, surface):
32 if options.debug:
33 self._render_shape(surface)
34
35 def animate(self):
36 # Used by time animatations to advance the clock
37 pass
38
39
40def image_pos(image, pos):
41 return (pos[0] - image.get_width() / 2,
42 pos[1] - image.get_height() / 2)
43
44
45class ImageRenderer(Renderer):
46 def __init__(self, image):
47 self._image = image
48
49 def get_image(self):
50 return self._image
51
52 def rotate_image(self, image):
53 angle = self.game_object.get_render_angle() * 180 / math.pi
54 return pygame.transform.rotate(image, angle)
55
56 def render_image(self, surface, image):
57 image = self.rotate_image(image)
58 pos = self.game_object.get_render_position(surface)
59 surface.blit(image, image_pos(image, pos))
60
61 def render(self, surface):
62 self.render_image(surface, self.get_image())
63 super(ImageRenderer, self).render(surface)
64
65
66class ImageStateRenderer(ImageRenderer):
67 def __init__(self, state_images):
68 self._state_images = state_images
69
70 def get_image(self):
71 return self._state_images[self.game_object.puzzler.get_state()]
72
73
[217]74class TimedAnimatedRenderer(ImageRenderer):
75 def __init__(self, images, frame_ticks=1):
76 self._images = images
77 self._frame_ticks = frame_ticks
78 self._frame_tick = 0
79 self._frame = 0
80
81 def advance_tick(self):
82 self._frame_tick += 1
83 if self._frame_tick > self._frame_ticks:
84 self._frame_tick = 0
85 self._frame += 1
86 if self._frame >= len(self._images):
87 self._frame = 0
88
89 def reset(self):
90 self._frame_tick = 0
91 self._frame = 0
92
93 def get_image(self):
94 return self._images[self._frame]
95
96 def animate(self):
97 self.advance_tick()
98
99
100class MovementAnimatedRenderer(TimedAnimatedRenderer):
101 def animate(self):
[218]102 if self.game_object.is_moving:
[217]103 self.advance_tick()
104 else:
105 self.reset()
106
107
108class RendererSelectionRenderer(Renderer):
109 def __init__(self, renderers):
110 self._renderers = renderers
111
112 def set_game_object(self, game_object):
113 self.game_object = game_object
114 for renderer in self._renderers.values():
115 renderer.set_game_object(game_object)
116
117 @property
118 def renderer(self):
119 return self._renderers[self.select_renderer()]
120
121 def render(self, surface):
122 return self.renderer.render(surface)
123
124 def animate(self):
125 return self.renderer.animate()
126
127 def select_renderer(self):
128 raise NotImplementedError()
129
130
131class FacingSelectionRenderer(RendererSelectionRenderer):
132 def __init__(self, renderers):
133 for renderer in renderers.values():
134 # TODO: Unhack this somehow.
135 renderer.rotate_image = self.rotate_image
136 super(FacingSelectionRenderer, self).__init__(renderers)
[207]137 self._face = 'left'
138
139 def _update_facing(self, angle):
140 if abs(angle) < math.pi / 2:
141 self._face = 'right'
142 elif abs(angle) > math.pi / 2:
143 self._face = 'left'
144
145 def rotate_image(self, image):
146 # Facing images don't get rotated.
147 return image
148
[217]149 def select_renderer(self):
[207]150 angle = self.game_object.get_render_angle()
151 self._update_facing(angle)
[217]152 return self._face
[207]153
154
155class ShapeRenderer(Renderer):
156 def render(self, surface):
157 self._render_shape(surface)
158 super(ShapeRenderer, self).render(surface)
159
160
161class ShapeStateRenderer(ShapeRenderer):
162 """Renders the shape in a different colour depending on the state.
163
164 Requires the game object it's attached to to have a puzzler.
165 """
166 def render(self, surface):
167 if self.game_object.puzzler.get_state():
168 color = pygame.color.THECOLORS['green']
169 else:
170 color = pygame.color.THECOLORS['red']
171
172 self.game_object.get_shape().color = color
173 super(ShapeStateRenderer, self).render(surface)
Note: See TracBrowser for help on using the repository browser.