comparison nagslang/protagonist.py @ 215:325c317cbfa1

Better protagonist physicser.
author Jeremy Thurgood <firxen@gmail.com>
date Wed, 04 Sep 2013 13:13:11 +0200
parents 3d54fe7a2998
children d98daba73055
comparison
equal deleted inserted replaced
214:d3d602a527bd 215:325c317cbfa1
3 3
4 import math 4 import math
5 5
6 from nagslang import render 6 from nagslang import render
7 from nagslang.constants import COLLISION_TYPE_PLAYER, ZORDER_MID 7 from nagslang.constants import COLLISION_TYPE_PLAYER, ZORDER_MID
8 from nagslang.game_object import GameObject, SingleShapePhysicser, make_body 8 from nagslang.game_object import GameObject, Physicser, make_body
9 from nagslang.mutators import FLIP_H 9 from nagslang.mutators import FLIP_H
10 from nagslang.resources import resources 10 from nagslang.resources import resources
11
12
13 class ProtagonistPhysicser(Physicser):
14 def __init__(self, space, form_shapes):
15 self._space = space
16 self._form_shapes = form_shapes
17
18 def switch_form(self, old_form, new_form):
19 self._space.remove(self._form_shapes[old_form])
20 shape = self._form_shapes[new_form]
21 self._space.add(shape)
22 for attr, value in shape.protagonist_body_props.iteritems():
23 setattr(shape.body, attr, value)
24
25 def get_shape(self):
26 return self._form_shapes[self.game_object.form]
11 27
12 28
13 class Protagonist(GameObject): 29 class Protagonist(GameObject):
14 """Representation of our fearless protagonist. 30 """Representation of our fearless protagonist.
15 31
20 HUMAN_FORM_BACK = 'human_back' 36 HUMAN_FORM_BACK = 'human_back'
21 WOLF_FORM = 'wolf' 37 WOLF_FORM = 'wolf'
22 WOLF_FORM_BACK = 'wolf_back' 38 WOLF_FORM_BACK = 'wolf_back'
23 39
24 def __init__(self, space, position): 40 def __init__(self, space, position):
25 self._setup_physics(space, position) 41 physicser = self._make_physics(space, position)
26 self._setup_renderers() 42 self._setup_renderers()
27 self.inventory = {} 43 self.inventory = {}
28 self.form = self.HUMAN_FORM 44 self.form = self.HUMAN_FORM
29 self.render_form = self.HUMAN_FORM 45 self.render_form = self.HUMAN_FORM
30 46
31 super(Protagonist, self).__init__( 47 super(Protagonist, self).__init__(
32 self._physicsers[self.form], self._renderers[self.form]) 48 physicser, self._renderers[self.form])
33 self.zorder = ZORDER_MID 49 self.zorder = ZORDER_MID
34 50
35 self.go_human() 51 self.go_human()
36 52
37 def _setup_physics(self, space, position): 53 def _make_physics(self, space, position):
38 self._body = make_body(10, pymunk.inf, position, 0.8) 54 body = make_body(10, pymunk.inf, position, 0.8)
39 55 body.velocity_limit = 1000
40 self._shapes = { 56
41 self.HUMAN_FORM: pymunk.Poly( 57 human = pymunk.Poly(body, [(-15, -30), (15, -30), (15, 30), (-15, 30)])
42 self._body, [(-15, -30), (15, -30), (15, 30), (-15, 30)]), 58 human.elasticity = 1.0
43 self.WOLF_FORM: pymunk.Circle(self._body, 30), 59 human.collision_type = COLLISION_TYPE_PLAYER
60 human.protagonist_body_props = {
61 'mass': 10,
62 'damping': 0.8,
44 } 63 }
45 self._shapes[self.HUMAN_FORM].friction = 1.0 64
46 self._shapes[self.WOLF_FORM].friction = 0.05 65 wolf = pymunk.Circle(body, 30)
47 self._physicsers = {} 66 wolf.elasticity = 1.0
48 for form, shape in self._shapes.iteritems(): 67 wolf.collision_type = COLLISION_TYPE_PLAYER
49 shape.elasticity = 1.0 68 wolf.protagonist_body_props = {
50 shape.collision_type = COLLISION_TYPE_PLAYER 69 'mass': 100,
51 self._physicsers[form] = SingleShapePhysicser(space, shape) 70 'damping': 0.9,
52 self.angle = 0 71 }
72
73 return ProtagonistPhysicser(space, {
74 self.HUMAN_FORM: human,
75 self.WOLF_FORM: wolf,
76 })
53 77
54 def _get_image(self, name, *transforms): 78 def _get_image(self, name, *transforms):
55 return resources.get_image('creatures', name, transforms=transforms) 79 return resources.get_image('creatures', name, transforms=transforms)
56 80
57 def _setup_renderers(self): 81 def _setup_renderers(self):
82 self.angle = 0
58 self._renderers = { 83 self._renderers = {
59 self.HUMAN_FORM: render.AnimatedFacingImageRenderer( 84 self.HUMAN_FORM: render.AnimatedFacingImageRenderer(
60 (self._get_image('human_1.png'), 85 (self._get_image('human_1.png'),
61 self._get_image('human_1.png'), 86 self._get_image('human_1.png'),
62 self._get_image('human_1.png'), 87 self._get_image('human_1.png'),
122 147
123 def get_render_angle(self): 148 def get_render_angle(self):
124 return self.angle 149 return self.angle
125 150
126 def go_werewolf(self): 151 def go_werewolf(self):
127 self._physicsers[self.form].remove_from_space() 152 self.physicser.switch_form(self.form, self.WOLF_FORM)
128 self.form = self.WOLF_FORM 153 self.form = self.WOLF_FORM
129 self._physicsers[self.form].add_to_space()
130 self.physicser = self._physicsers[self.form]
131 self._body.mass = 100
132 self._body.velocity_limit = 1000
133 self.impulse_factor = 4000 154 self.impulse_factor = 4000
134 self._body.damping = 0.9 155
135 if self.render_form == self.HUMAN_FORM: 156 if self.render_form == self.HUMAN_FORM:
136 self.render_form = self.WOLF_FORM 157 self.render_form = self.WOLF_FORM
137 elif self.render_form == self.HUMAN_FORM_BACK: 158 elif self.render_form == self.HUMAN_FORM_BACK:
138 self.render_form = self.WOLF_FORM_BACK 159 self.render_form = self.WOLF_FORM_BACK
139 else: 160 else:
140 self.render_form = self.WOLF_FORM 161 self.render_form = self.WOLF_FORM
141 self.renderer = self._renderers[self.render_form] 162 self.renderer = self._renderers[self.render_form]
142 163
143 def go_human(self): 164 def go_human(self):
144 self._physicsers[self.form].remove_from_space() 165 self.physicser.switch_form(self.form, self.HUMAN_FORM)
145 self.form = self.HUMAN_FORM 166 self.form = self.HUMAN_FORM
146 self._physicsers[self.form].add_to_space()
147 self.physicser = self._physicsers[self.form]
148 self._body.mass = 10
149 self._body.velocity_limit = 1000
150 self.impulse_factor = 500 167 self.impulse_factor = 500
151 self._body.damping = 0.8 168
152 if self.render_form == self.WOLF_FORM: 169 if self.render_form == self.WOLF_FORM:
153 self.render_form = self.HUMAN_FORM 170 self.render_form = self.HUMAN_FORM
154 elif self.render_form == self.WOLF_FORM_BACK: 171 elif self.render_form == self.WOLF_FORM_BACK:
155 self.render_form = self.HUMAN_FORM_BACK 172 self.render_form = self.HUMAN_FORM_BACK
156 else: 173 else:
184 # trigger a front/back swap and simplifies these checks 201 # trigger a front/back swap and simplifies these checks
185 if self.angle > 0 and old_angle != self.angle: 202 if self.angle > 0 and old_angle != self.angle:
186 self._switch_to_back() 203 self._switch_to_back()
187 elif self.angle < 0 and old_angle != self.angle: 204 elif self.angle < 0 and old_angle != self.angle:
188 self._switch_to_front() 205 self._switch_to_front()
189 self._body.apply_impulse( 206 self.physicser.apply_impulse(
190 (dx * self.impulse_factor, dy * self.impulse_factor)) 207 (dx * self.impulse_factor, dy * self.impulse_factor))
191 self.renderer.start() 208 self.renderer.start()
192 209
193 def set_position(self, position): 210 def set_position(self, position):
194 self._body.position = position 211 self.physicser.position = position
195 212
196 def copy_state(self, old_protagonist): 213 def copy_state(self, old_protagonist):
197 self._physicsers[self.form].remove_from_space() 214 self.physicser.position = old_protagonist.physicser.position
198 self._body.position = old_protagonist._body.position 215 self.physicser.switch_form(self.form, old_protagonist.form)
199 self.form = old_protagonist.form 216 self.form = old_protagonist.form
200 self.angle = old_protagonist.angle 217 self.angle = old_protagonist.angle
201 self.render_form = old_protagonist.render_form 218 self.render_form = old_protagonist.render_form
202 self.inventory = old_protagonist.inventory 219 self.inventory = old_protagonist.inventory
203 self.renderer = self._renderers[self.render_form] 220 self.renderer = self._renderers[self.render_form]
204 self._physicsers[self.form].add_to_space()
205 self.physicser = self._physicsers[self.form]
206 221
207 def toggle_form(self): 222 def toggle_form(self):
208 if self.form == self.WOLF_FORM: 223 if self.form == self.WOLF_FORM:
209 self.go_human() 224 self.go_human()
210 else: 225 else:
231 return item in self.inventory 246 return item in self.inventory
232 247
233 def environmental_movement(self, dx, dy): 248 def environmental_movement(self, dx, dy):
234 if (dx, dy) == (0, 0): 249 if (dx, dy) == (0, 0):
235 return 250 return
236 self._body.apply_impulse((dx, dy)) 251 self.physicser.apply_impulse((dx, dy))