source: nagslang/render.py@ 219:f9e92d540bfa

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

Less hacky rotation suppression.

File size: 4.9 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):
[219]46 rotate = True # Set to `False` to suppress image rotation.
47
[207]48 def __init__(self, image):
49 self._image = image
50
51 def get_image(self):
52 return self._image
53
54 def rotate_image(self, image):
[219]55 if not self._rotate:
56 return image
[207]57 angle = self.game_object.get_render_angle() * 180 / math.pi
58 return pygame.transform.rotate(image, angle)
59
60 def render_image(self, surface, image):
61 image = self.rotate_image(image)
62 pos = self.game_object.get_render_position(surface)
63 surface.blit(image, image_pos(image, pos))
64
65 def render(self, surface):
66 self.render_image(surface, self.get_image())
67 super(ImageRenderer, self).render(surface)
68
69
70class ImageStateRenderer(ImageRenderer):
71 def __init__(self, state_images):
72 self._state_images = state_images
73
74 def get_image(self):
75 return self._state_images[self.game_object.puzzler.get_state()]
76
77
[217]78class TimedAnimatedRenderer(ImageRenderer):
79 def __init__(self, images, frame_ticks=1):
80 self._images = images
81 self._frame_ticks = frame_ticks
82 self._frame_tick = 0
83 self._frame = 0
84
85 def advance_tick(self):
86 self._frame_tick += 1
87 if self._frame_tick > self._frame_ticks:
88 self._frame_tick = 0
89 self._frame += 1
90 if self._frame >= len(self._images):
91 self._frame = 0
92
93 def reset(self):
94 self._frame_tick = 0
95 self._frame = 0
96
97 def get_image(self):
98 return self._images[self._frame]
99
100 def animate(self):
101 self.advance_tick()
102
103
104class MovementAnimatedRenderer(TimedAnimatedRenderer):
105 def animate(self):
[218]106 if self.game_object.is_moving:
[217]107 self.advance_tick()
108 else:
109 self.reset()
110
111
112class RendererSelectionRenderer(Renderer):
113 def __init__(self, renderers):
114 self._renderers = renderers
115
116 def set_game_object(self, game_object):
117 self.game_object = game_object
118 for renderer in self._renderers.values():
119 renderer.set_game_object(game_object)
120
121 @property
122 def renderer(self):
123 return self._renderers[self.select_renderer()]
124
125 def render(self, surface):
126 return self.renderer.render(surface)
127
128 def animate(self):
129 return self.renderer.animate()
130
131 def select_renderer(self):
132 raise NotImplementedError()
133
134
135class FacingSelectionRenderer(RendererSelectionRenderer):
136 def __init__(self, renderers):
137 for renderer in renderers.values():
[219]138 renderer.rotate = False
[217]139 super(FacingSelectionRenderer, self).__init__(renderers)
[207]140 self._face = 'left'
141
142 def _update_facing(self, angle):
143 if abs(angle) < math.pi / 2:
144 self._face = 'right'
145 elif abs(angle) > math.pi / 2:
146 self._face = 'left'
147
[217]148 def select_renderer(self):
[207]149 angle = self.game_object.get_render_angle()
150 self._update_facing(angle)
[217]151 return self._face
[207]152
153
154class ShapeRenderer(Renderer):
155 def render(self, surface):
156 self._render_shape(surface)
157 super(ShapeRenderer, self).render(surface)
158
159
160class ShapeStateRenderer(ShapeRenderer):
161 """Renders the shape in a different colour depending on the state.
162
163 Requires the game object it's attached to to have a puzzler.
164 """
165 def render(self, surface):
166 if self.game_object.puzzler.get_state():
167 color = pygame.color.THECOLORS['green']
168 else:
169 color = pygame.color.THECOLORS['red']
170
171 self.game_object.get_shape().color = color
172 super(ShapeStateRenderer, self).render(surface)
Note: See TracBrowser for help on using the repository browser.