Mercurial > nagslang
annotate nagslang/render.py @ 378:8069c9be1c3e
Create a nagslang.collectable module for collectables
author | Stefano Rivera <stefano@rivera.za.net> |
---|---|
date | Fri, 06 Sep 2013 23:07:27 +0200 |
parents | d0aeb893967d |
children | 8a65fd894f73 |
rev | line source |
---|---|
207 | 1 import math |
2 | |
3 import pygame | |
349 | 4 import pygame.locals as pgl |
207 | 5 import pymunk |
6 | |
7 from nagslang.options import options | |
349 | 8 from nagslang.utils import tile_surface |
222
cc5f2a5ac501
Overlays belong in render
Stefano Rivera <stefano@rivera.za.net>
parents:
221
diff
changeset
|
9 from nagslang.widgets.text import LabelWidget |
207 | 10 |
11 | |
12 class Renderer(object): | |
13 def set_game_object(self, game_object): | |
14 self.game_object = game_object | |
15 | |
16 def _render_shape(self, surface): | |
17 shape = self.game_object.get_shape() | |
18 # Less general that pymunk.pygame_util.draw, but also a lot less noisy. | |
19 color = getattr(shape, 'color', pygame.color.THECOLORS['lightblue']) | |
20 # We only explicitly draw Circle and Poly shapes. Everything else we | |
21 # forward to pymunk. | |
22 if isinstance(shape, pymunk.Circle): | |
23 centre = pymunk.pygame_util.to_pygame(shape.body.position, surface) | |
24 radius = int(shape.radius) | |
25 pygame.draw.circle(surface, color, centre, radius, 2) | |
26 elif isinstance(shape, pymunk.Poly): | |
27 # polygon bounding box | |
28 points = [pymunk.pygame_util.to_pygame(p, surface) | |
29 for p in shape.get_vertices()] | |
30 pygame.draw.lines(surface, color, True, points, 2) | |
31 else: | |
32 pymunk.pygame_util.draw(surface, shape) | |
33 | |
34 def render(self, surface): | |
35 if options.debug: | |
36 self._render_shape(surface) | |
37 | |
307
c2bbb1e70d6f
Rename animate to update and pass seconds, for future fun
Neil Muller <drnlmuller@gmail.com>
parents:
286
diff
changeset
|
38 def update(self, seconds): |
207 | 39 # Used by time animatations to advance the clock |
40 pass | |
41 | |
42 | |
286
248b8fdb160c
Collect gun (which currently looks like a bullet) to shoot.
Jeremy Thurgood <firxen@gmail.com>
parents:
230
diff
changeset
|
43 class NullRenderer(Renderer): |
248b8fdb160c
Collect gun (which currently looks like a bullet) to shoot.
Jeremy Thurgood <firxen@gmail.com>
parents:
230
diff
changeset
|
44 def render(self, surface): |
248b8fdb160c
Collect gun (which currently looks like a bullet) to shoot.
Jeremy Thurgood <firxen@gmail.com>
parents:
230
diff
changeset
|
45 pass |
248b8fdb160c
Collect gun (which currently looks like a bullet) to shoot.
Jeremy Thurgood <firxen@gmail.com>
parents:
230
diff
changeset
|
46 |
248b8fdb160c
Collect gun (which currently looks like a bullet) to shoot.
Jeremy Thurgood <firxen@gmail.com>
parents:
230
diff
changeset
|
47 |
207 | 48 def image_pos(image, pos): |
49 return (pos[0] - image.get_width() / 2, | |
50 pos[1] - image.get_height() / 2) | |
51 | |
52 | |
53 class ImageRenderer(Renderer): | |
54 def __init__(self, image): | |
55 self._image = image | |
56 | |
57 def get_image(self): | |
58 return self._image | |
59 | |
60 def rotate_image(self, image): | |
61 angle = self.game_object.get_render_angle() * 180 / math.pi | |
62 return pygame.transform.rotate(image, angle) | |
63 | |
64 def render_image(self, surface, image): | |
65 image = self.rotate_image(image) | |
66 pos = self.game_object.get_render_position(surface) | |
67 surface.blit(image, image_pos(image, pos)) | |
68 | |
69 def render(self, surface): | |
70 self.render_image(surface, self.get_image()) | |
71 super(ImageRenderer, self).render(surface) | |
72 | |
73 | |
74 class ImageStateRenderer(ImageRenderer): | |
75 def __init__(self, state_images): | |
76 self._state_images = state_images | |
77 | |
78 def get_image(self): | |
79 return self._state_images[self.game_object.puzzler.get_state()] | |
80 | |
81 | |
217
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
82 class TimedAnimatedRenderer(ImageRenderer): |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
83 def __init__(self, images, frame_ticks=1): |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
84 self._images = images |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
85 self._frame_ticks = frame_ticks |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
86 self._frame_tick = 0 |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
87 self._frame = 0 |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
88 |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
89 def advance_tick(self): |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
90 self._frame_tick += 1 |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
91 if self._frame_tick > self._frame_ticks: |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
92 self._frame_tick = 0 |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
93 self._frame += 1 |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
94 if self._frame >= len(self._images): |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
95 self._frame = 0 |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
96 |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
97 def reset(self): |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
98 self._frame_tick = 0 |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
99 self._frame = 0 |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
100 |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
101 def get_image(self): |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
102 return self._images[self._frame] |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
103 |
307
c2bbb1e70d6f
Rename animate to update and pass seconds, for future fun
Neil Muller <drnlmuller@gmail.com>
parents:
286
diff
changeset
|
104 def update(self, seconds): |
217
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
105 self.advance_tick() |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
106 |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
107 |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
108 class MovementAnimatedRenderer(TimedAnimatedRenderer): |
307
c2bbb1e70d6f
Rename animate to update and pass seconds, for future fun
Neil Muller <drnlmuller@gmail.com>
parents:
286
diff
changeset
|
109 def update(self, seconds): |
218
9e2ef2f15035
Better rendering and movement detection.
Jeremy Thurgood <firxen@gmail.com>
parents:
217
diff
changeset
|
110 if self.game_object.is_moving: |
217
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
111 self.advance_tick() |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
112 else: |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
113 self.reset() |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
114 |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
115 |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
116 class RendererSelectionRenderer(Renderer): |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
117 def __init__(self, renderers): |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
118 self._renderers = renderers |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
119 |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
120 def set_game_object(self, game_object): |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
121 self.game_object = game_object |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
122 for renderer in self._renderers.values(): |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
123 renderer.set_game_object(game_object) |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
124 |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
125 @property |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
126 def renderer(self): |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
127 return self._renderers[self.select_renderer()] |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
128 |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
129 def render(self, surface): |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
130 return self.renderer.render(surface) |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
131 |
307
c2bbb1e70d6f
Rename animate to update and pass seconds, for future fun
Neil Muller <drnlmuller@gmail.com>
parents:
286
diff
changeset
|
132 def update(self, seconds): |
c2bbb1e70d6f
Rename animate to update and pass seconds, for future fun
Neil Muller <drnlmuller@gmail.com>
parents:
286
diff
changeset
|
133 return self.renderer.update(seconds) |
217
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
134 |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
135 def select_renderer(self): |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
136 raise NotImplementedError() |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
137 |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
138 |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
139 class FacingSelectionRenderer(RendererSelectionRenderer): |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
140 def select_renderer(self): |
229
329b3044ddef
Much better facing renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
222
diff
changeset
|
141 return self.game_object.get_facing_direction() |
207 | 142 |
143 | |
144 class ShapeRenderer(Renderer): | |
145 def render(self, surface): | |
146 self._render_shape(surface) | |
147 super(ShapeRenderer, self).render(surface) | |
148 | |
149 | |
150 class ShapeStateRenderer(ShapeRenderer): | |
151 """Renders the shape in a different colour depending on the state. | |
152 | |
153 Requires the game object it's attached to to have a puzzler. | |
154 """ | |
155 def render(self, surface): | |
156 if self.game_object.puzzler.get_state(): | |
157 color = pygame.color.THECOLORS['green'] | |
158 else: | |
159 color = pygame.color.THECOLORS['red'] | |
160 | |
161 self.game_object.get_shape().color = color | |
162 super(ShapeStateRenderer, self).render(surface) | |
222
cc5f2a5ac501
Overlays belong in render
Stefano Rivera <stefano@rivera.za.net>
parents:
221
diff
changeset
|
163 |
cc5f2a5ac501
Overlays belong in render
Stefano Rivera <stefano@rivera.za.net>
parents:
221
diff
changeset
|
164 |
cc5f2a5ac501
Overlays belong in render
Stefano Rivera <stefano@rivera.za.net>
parents:
221
diff
changeset
|
165 class Overlay(object): |
cc5f2a5ac501
Overlays belong in render
Stefano Rivera <stefano@rivera.za.net>
parents:
221
diff
changeset
|
166 def set_game_object(self, game_object): |
cc5f2a5ac501
Overlays belong in render
Stefano Rivera <stefano@rivera.za.net>
parents:
221
diff
changeset
|
167 self.game_object = game_object |
cc5f2a5ac501
Overlays belong in render
Stefano Rivera <stefano@rivera.za.net>
parents:
221
diff
changeset
|
168 |
cc5f2a5ac501
Overlays belong in render
Stefano Rivera <stefano@rivera.za.net>
parents:
221
diff
changeset
|
169 def render(self, surface, display_offset): |
cc5f2a5ac501
Overlays belong in render
Stefano Rivera <stefano@rivera.za.net>
parents:
221
diff
changeset
|
170 pass |
cc5f2a5ac501
Overlays belong in render
Stefano Rivera <stefano@rivera.za.net>
parents:
221
diff
changeset
|
171 |
cc5f2a5ac501
Overlays belong in render
Stefano Rivera <stefano@rivera.za.net>
parents:
221
diff
changeset
|
172 def is_visible(self): |
cc5f2a5ac501
Overlays belong in render
Stefano Rivera <stefano@rivera.za.net>
parents:
221
diff
changeset
|
173 return self.game_object.puzzler.get_state() |
cc5f2a5ac501
Overlays belong in render
Stefano Rivera <stefano@rivera.za.net>
parents:
221
diff
changeset
|
174 |
cc5f2a5ac501
Overlays belong in render
Stefano Rivera <stefano@rivera.za.net>
parents:
221
diff
changeset
|
175 |
cc5f2a5ac501
Overlays belong in render
Stefano Rivera <stefano@rivera.za.net>
parents:
221
diff
changeset
|
176 class TextOverlay(Overlay): |
cc5f2a5ac501
Overlays belong in render
Stefano Rivera <stefano@rivera.za.net>
parents:
221
diff
changeset
|
177 def __init__(self, text): |
cc5f2a5ac501
Overlays belong in render
Stefano Rivera <stefano@rivera.za.net>
parents:
221
diff
changeset
|
178 self.text = text |
cc5f2a5ac501
Overlays belong in render
Stefano Rivera <stefano@rivera.za.net>
parents:
221
diff
changeset
|
179 self.widget = LabelWidget((20, 20), self.text) |
cc5f2a5ac501
Overlays belong in render
Stefano Rivera <stefano@rivera.za.net>
parents:
221
diff
changeset
|
180 |
cc5f2a5ac501
Overlays belong in render
Stefano Rivera <stefano@rivera.za.net>
parents:
221
diff
changeset
|
181 def render(self, surface, display_offset): |
cc5f2a5ac501
Overlays belong in render
Stefano Rivera <stefano@rivera.za.net>
parents:
221
diff
changeset
|
182 x, y = 20, 20 |
cc5f2a5ac501
Overlays belong in render
Stefano Rivera <stefano@rivera.za.net>
parents:
221
diff
changeset
|
183 if display_offset[0] < 0: |
cc5f2a5ac501
Overlays belong in render
Stefano Rivera <stefano@rivera.za.net>
parents:
221
diff
changeset
|
184 x += abs(display_offset[0]) |
cc5f2a5ac501
Overlays belong in render
Stefano Rivera <stefano@rivera.za.net>
parents:
221
diff
changeset
|
185 if display_offset[1] < 0: |
cc5f2a5ac501
Overlays belong in render
Stefano Rivera <stefano@rivera.za.net>
parents:
221
diff
changeset
|
186 y += abs(display_offset[1]) |
cc5f2a5ac501
Overlays belong in render
Stefano Rivera <stefano@rivera.za.net>
parents:
221
diff
changeset
|
187 self.widget.rect.topleft = (x, y) |
cc5f2a5ac501
Overlays belong in render
Stefano Rivera <stefano@rivera.za.net>
parents:
221
diff
changeset
|
188 self.widget.draw(surface) |
349 | 189 |
190 | |
191 class TiledRenderer(Renderer): | |
192 """Tile the given image to fit the given outline | |
193 | |
194 Outline is assumed to be in pymunk coordinates""" | |
195 | |
362 | 196 def __init__(self, outline, tile_image, alpha=255): |
349 | 197 self._tile_image = tile_image |
198 self.outline = outline | |
199 self._tiled = None | |
353 | 200 self._offset = None |
362 | 201 self._alpha = alpha |
349 | 202 |
203 def _make_surface(self, surface): | |
204 if not self._tiled: | |
205 size = surface.get_size() | |
206 mask = pygame.surface.Surface(size, pgl.SRCALPHA) | |
207 mask.fill(pygame.color.Color(0, 0, 0, 0)) | |
208 pointlist = [pymunk.pygame_util.to_pygame(p, surface) | |
209 for p in self.outline] | |
362 | 210 rect = pygame.draw.polygon(mask, |
211 pygame.color.Color( | |
212 255, 255, 255, self._alpha), | |
353 | 213 pointlist, 0) |
214 self._offset = (rect.x, rect.y) | |
215 self._tiled = tile_surface((rect.w, rect.h), self._tile_image) | |
216 self._tiled.blit(mask, (0, 0), rect, | |
217 special_flags=pgl.BLEND_RGBA_MULT) | |
349 | 218 |
219 def render(self, surface): | |
353 | 220 self._make_surface(surface) |
221 surface.blit(self._tiled, self._offset) | |
349 | 222 super(TiledRenderer, self).render(surface) |