comparison nagslang/game_object.py @ 123:23b533d6f27e

Rearrange game objects a bit.
author Jeremy Thurgood <firxen@gmail.com>
date Mon, 02 Sep 2013 16:43:15 +0200
parents b90d01e4d9d4
children c3af35561494
comparison
equal deleted inserted replaced
122:02423600d958 123:23b533d6f27e
27 """Behaviour specific to a puzzle component. 27 """Behaviour specific to a puzzle component.
28 """ 28 """
29 def set_glue(self, glue): 29 def set_glue(self, glue):
30 self.glue = glue 30 self.glue = glue
31 31
32 def set_game_object(self, game_object):
33 self.game_object = game_object
34
32 def get_state(self): 35 def get_state(self):
33 raise NotImplementedError() 36 raise NotImplementedError()
34 37
35 38
36 class FloorSwitchPuzzler(Puzzler): 39 class FloorSwitchPuzzler(Puzzler):
37 def __init__(self, space, shape):
38 self._space = space
39 self._shape = shape
40
41 def get_state(self): 40 def get_state(self):
42 for shape in self._space.shape_query(self._shape): 41 space = self.game_object.get_space()
42 for shape in space.shape_query(self.game_object.get_shape()):
43 if shape.collision_type in SWITCH_PUSHERS: 43 if shape.collision_type in SWITCH_PUSHERS:
44 return True 44 return True
45 return False 45 return False
46 46
47 47
53 return self.glue.get_state_of(self._state_source) 53 return self.glue.get_state_of(self._state_source)
54 54
55 55
56 class Physicser(object): 56 class Physicser(object):
57 def __init__(self, space): 57 def __init__(self, space):
58 self.space = space 58 self._space = space
59
60 def get_space(self):
61 return self._space
62
63 def set_game_object(self, game_object):
64 self.game_object = game_object
65
66 def get_shape(self):
67 raise NotImplementedError()
59 68
60 def add_to_space(self): 69 def add_to_space(self):
61 raise NotImplementedError() 70 raise NotImplementedError()
62 71
63 def remove_from_space(self): 72 def remove_from_space(self):
76 class SingleShapePhysicser(Physicser): 85 class SingleShapePhysicser(Physicser):
77 def __init__(self, space, shape): 86 def __init__(self, space, shape):
78 super(SingleShapePhysicser, self).__init__(space) 87 super(SingleShapePhysicser, self).__init__(space)
79 self._shape = shape 88 self._shape = shape
80 89
90 def get_shape(self):
91 return self._shape
92
81 def add_to_space(self): 93 def add_to_space(self):
82 self.space.add(self._shape) 94 self.get_space().add(self._shape)
83 if not self._shape.body.is_static: 95 if not self._shape.body.is_static:
84 self.space.add(self._shape.body) 96 self.get_space().add(self._shape.body)
85 97
86 def remove_from_space(self): 98 def remove_from_space(self):
87 self.space.remove(self._shape) 99 self.get_space().remove(self._shape)
88 if not self._shape.body.is_static: 100 if not self._shape.body.is_static:
89 self.space.remove(self._shape.body) 101 self.get_space().remove(self._shape.body)
90 102
91 def get_render_position(self, surface): 103 def get_render_position(self, surface):
92 pos = self._shape.body.position 104 pos = self._shape.body.position
93 return pymunk.pygame_util.to_pygame(pos, surface) 105 return pymunk.pygame_util.to_pygame(pos, surface)
94 106
98 def apply_impulse(self, j, r=(0, 0)): 110 def apply_impulse(self, j, r=(0, 0)):
99 return self._shape.body.apply_impulse(j, r) 111 return self._shape.body.apply_impulse(j, r)
100 112
101 113
102 class Renderer(object): 114 class Renderer(object):
103 def __init__(self, shape): 115 def set_game_object(self, game_object):
104 self._shape = shape 116 self.game_object = game_object
105 117
106 def _render_shape(self, surface, pos, angle): 118 def _render_shape(self, surface):
119 shape = self.game_object.get_shape()
107 # Less general that pymunk.pygame_util.draw, but also a lot less noisy. 120 # Less general that pymunk.pygame_util.draw, but also a lot less noisy.
108 color = getattr( 121 color = getattr(shape, 'color', pygame.color.THECOLORS['lightblue'])
109 self._shape, 'color', pygame.color.THECOLORS['lightblue'])
110 # We only explicitly draw Circle and Poly shapes. Everything else we 122 # We only explicitly draw Circle and Poly shapes. Everything else we
111 # forward to pymunk. 123 # forward to pymunk.
112 if isinstance(self._shape, pymunk.Circle): 124 if isinstance(shape, pymunk.Circle):
113 centre = pymunk.pygame_util.to_pygame( 125 centre = pymunk.pygame_util.to_pygame(shape.body.position, surface)
114 self._shape.body.position, surface) 126 radius = int(shape.radius)
115 radius = int(self._shape.radius)
116 pygame.draw.circle(surface, color, centre, radius, 2) 127 pygame.draw.circle(surface, color, centre, radius, 2)
117 elif isinstance(self._shape, pymunk.Poly): 128 elif isinstance(shape, pymunk.Poly):
118 # polygon bounding box 129 # polygon bounding box
119 points = [pymunk.pygame_util.to_pygame(p, surface) 130 points = [pymunk.pygame_util.to_pygame(p, surface)
120 for p in self._shape.get_vertices()] 131 for p in shape.get_vertices()]
121 pygame.draw.lines(surface, color, True, points, 2) 132 pygame.draw.lines(surface, color, True, points, 2)
122 else: 133 else:
123 pymunk.pygame_util.draw(surface, self._shape) 134 pymunk.pygame_util.draw(surface, shape)
124 135
125 def render(self, surface, pos, angle): 136 def render(self, surface):
137 pos = self.game_object.get_render_position(surface)
138 angle = self.game_object.get_render_angle()
126 if options.debug: 139 if options.debug:
127 self._render_shape(surface, pos, angle) 140 self._render_shape(surface, pos, angle)
128 141
129 142
130 def image_pos(image, pos): 143 def image_pos(image, pos):
131 return (pos[0] - image.get_width() / 2, 144 return (pos[0] - image.get_width() / 2,
132 pos[1] - image.get_height() / 2) 145 pos[1] - image.get_height() / 2)
133 146
134 147
135 class ImageRenderer(Renderer): 148 class ImageRenderer(Renderer):
136 def __init__(self, shape, image): 149 def __init__(self, image):
137 super(ImageRenderer, self).__init__(shape)
138 self._image = image 150 self._image = image
139 151
140 def render(self, surface, pos, angle): 152 def render(self, surface):
153 pos = self.game_object.get_render_position(surface)
141 surface.blit(self._image, image_pos(self._image, pos)) 154 surface.blit(self._image, image_pos(self._image, pos))
142 super(ImageRenderer, self).render(surface, pos, angle) 155 super(ImageRenderer, self).render(surface)
143 156
144 157
145 class FacingImageRenderer(Renderer): 158 class FacingImageRenderer(Renderer):
146 def __init__(self, shape, left_image, right_image): 159 def __init__(self, left_image, right_image):
147 super(FacingImageRenderer, self).__init__(shape)
148 self._images = { 160 self._images = {
149 'left': left_image, 161 'left': left_image,
150 'right': right_image, 162 'right': right_image,
151 } 163 }
152 164
153 def get_image(self, angle): 165 def get_image(self, angle):
154 if abs(angle) < math.pi / 2: 166 if abs(angle) < math.pi / 2:
155 return self._images['right'] 167 return self._images['right']
156 return self._images['left'] 168 return self._images['left']
157 169
158 def render(self, surface, pos, angle): 170 def render(self, surface):
159 image = self.get_image(angle) 171 pos = self.game_object.get_render_position(surface)
172 image = self.get_image(self.game_object.get_render_angle())
160 surface.blit(image, image_pos(image, pos)) 173 surface.blit(image, image_pos(image, pos))
161 super(FacingImageRenderer, self).render(surface, pos, angle) 174 super(FacingImageRenderer, self).render(surface)
162 175
163 176
164 class ShapeRenderer(Renderer): 177 class ShapeRenderer(Renderer):
165 def render(self, surface, pos, angle): 178 def render(self, surface):
166 self._render_shape(surface, pos, angle) 179 self._render_shape(surface)
167 super(ShapeRenderer, self).render(surface, pos, angle) 180 super(ShapeRenderer, self).render(surface)
168 181
169 182
170 class GameObject(object): 183 class GameObject(object):
171 """A representation of a thing in the game world. 184 """A representation of a thing in the game world.
172 185
173 This has a rendery thing, physicsy things and maybe some other things. 186 This has a rendery thing, physicsy things and maybe some other things.
174 """ 187 """
175 188
176 def __init__(self, physicser, renderer, puzzler=None): 189 def __init__(self, physicser, renderer, puzzler=None):
177 self.physicser = physicser 190 self.physicser = physicser
191 physicser.set_game_object(self)
178 self.physicser.add_to_space() 192 self.physicser.add_to_space()
179 self.renderer = renderer 193 self.renderer = renderer
194 renderer.set_game_object(self)
180 self.puzzler = puzzler 195 self.puzzler = puzzler
196 if puzzler is not None:
197 puzzler.set_game_object(self)
181 self.zorder = ZORDER_LOW 198 self.zorder = ZORDER_LOW
199
200 def get_space(self):
201 return self.physicser.get_space()
202
203 def get_shape(self):
204 return self.physicser.get_shape()
182 205
183 def get_render_position(self, surface): 206 def get_render_position(self, surface):
184 return self.physicser.get_render_position(surface) 207 return self.physicser.get_render_position(surface)
185 208
186 def get_render_angle(self): 209 def get_render_angle(self):
187 return self.physicser.get_angle() 210 return self.physicser.get_angle()
188 211
189 def render(self, surface): 212 def render(self, surface):
190 return self.renderer.render( 213 return self.renderer.render(surface)
191 surface, self.get_render_position(surface),
192 self.get_render_angle())
193 214
194 215
195 class FloorSwitch(GameObject): 216 class FloorSwitch(GameObject):
196 def __init__(self, space, position): 217 def __init__(self, space, position):
197 body = pymunk.Body() 218 body = pymunk.Body()
199 self.shape = pymunk.Circle(body, 30) 220 self.shape = pymunk.Circle(body, 30)
200 self.shape.collision_type = COLLISION_TYPE_SWITCH 221 self.shape.collision_type = COLLISION_TYPE_SWITCH
201 self.shape.sensor = True 222 self.shape.sensor = True
202 super(FloorSwitch, self).__init__( 223 super(FloorSwitch, self).__init__(
203 SingleShapePhysicser(space, self.shape), 224 SingleShapePhysicser(space, self.shape),
204 ShapeRenderer(self.shape), 225 ShapeRenderer(),
205 FloorSwitchPuzzler(space, self.shape), 226 FloorSwitchPuzzler(),
206 ) 227 )
207 228
208 def render(self, surface): 229 def render(self, surface):
209 if self.puzzler.get_state(): 230 if self.puzzler.get_state():
210 self.shape.color = pygame.color.THECOLORS['green'] 231 self.shape.color = pygame.color.THECOLORS['green']
220 self.shape = pymunk.Circle(body, 10) 241 self.shape = pymunk.Circle(body, 10)
221 self.shape.collision_type = COLLISION_TYPE_SWITCH 242 self.shape.collision_type = COLLISION_TYPE_SWITCH
222 self.shape.sensor = True 243 self.shape.sensor = True
223 super(FloorLight, self).__init__( 244 super(FloorLight, self).__init__(
224 SingleShapePhysicser(space, self.shape), 245 SingleShapePhysicser(space, self.shape),
225 ShapeRenderer(self.shape), 246 ShapeRenderer(),
226 StateProxyPuzzler(state_source), 247 StateProxyPuzzler(state_source),
227 ) 248 )
228 249
229 def render(self, surface): 250 def render(self, surface):
230 if self.puzzler.get_state(): 251 if self.puzzler.get_state():