source: nagslang/protagonist.py@ 207:42e8993c31fd

Last change on this file since 207:42e8993c31fd was 207:42e8993c31fd, checked in by Stefano Rivera <stefano@…>, 8 years ago

Break out Renderers

File size: 9.0 KB
RevLine 
[65]1import pymunk
2import pymunk.pygame_util
3
[156]4import math
5
[207]6from nagslang import render
[107]7from nagslang.constants import COLLISION_TYPE_PLAYER, ZORDER_MID
[207]8from nagslang.game_object import GameObject, SingleShapePhysicser, make_body
[76]9from nagslang.mutators import FLIP_H
[65]10from nagslang.resources import resources
[28]11
12
[65]13class Protagonist(GameObject):
[28]14 """Representation of our fearless protagonist.
15
16 TODO: Factor out a bunch of this stuff when we need it for other objects.
17 """
18
19 HUMAN_FORM = 'human'
[156]20 HUMAN_FORM_BACK = 'human_back'
[28]21 WOLF_FORM = 'wolf'
[156]22 WOLF_FORM_BACK = 'wolf_back'
[28]23
[93]24 def __init__(self, space, position):
25 self._setup_physics(space, position)
[65]26 self._setup_renderers()
[28]27 self.inventory = {}
28 self.form = self.HUMAN_FORM
[156]29 self.render_form = self.HUMAN_FORM
[28]30
[65]31 super(Protagonist, self).__init__(
[93]32 self._physicsers[self.form], self._renderers[self.form])
[107]33 self.zorder = ZORDER_MID
[65]34
35 self.go_human()
36
[93]37 def _setup_physics(self, space, position):
[133]38 self._body = make_body(10, pymunk.inf, position, 0.8)
[65]39
[93]40 self._shapes = {
41 self.HUMAN_FORM: pymunk.Poly(
42 self._body, [(-15, -30), (15, -30), (15, 30), (-15, 30)]),
43 self.WOLF_FORM: pymunk.Circle(self._body, 30),
44 }
45 self._physicsers = {}
46 for form, shape in self._shapes.iteritems():
47 shape.elasticity = 1.0
48 shape.friction = 10.0
49 shape.collision_type = COLLISION_TYPE_PLAYER
50 self._physicsers[form] = SingleShapePhysicser(space, shape)
51 self.angle = 0
[65]52
[66]53 def _get_image(self, name, *transforms):
54 return resources.get_image('creatures', name, transforms=transforms)
55
[65]56 def _setup_renderers(self):
57 self._renderers = {
[207]58 self.HUMAN_FORM: render.AnimatedFacingImageRenderer(
[143]59 (self._get_image('human_1.png'),
60 self._get_image('human_1.png'),
61 self._get_image('human_1.png'),
62 self._get_image('human_2.png'),
63 self._get_image('human_2.png'),
64 self._get_image('human_2.png')),
65 (self._get_image('human_1.png', FLIP_H),
66 self._get_image('human_1.png', FLIP_H),
67 self._get_image('human_1.png', FLIP_H),
68 self._get_image('human_2.png', FLIP_H),
69 self._get_image('human_2.png', FLIP_H),
70 self._get_image('human_2.png', FLIP_H))),
[207]71 self.HUMAN_FORM_BACK: render.AnimatedFacingImageRenderer(
[156]72 (self._get_image('human_back_1.png'),
73 self._get_image('human_back_1.png'),
74 self._get_image('human_back_1.png'),
75 self._get_image('human_back_2.png'),
76 self._get_image('human_back_2.png'),
77 self._get_image('human_back_2.png')),
78 (self._get_image('human_back_1.png', FLIP_H),
79 self._get_image('human_back_1.png', FLIP_H),
80 self._get_image('human_back_1.png', FLIP_H),
81 self._get_image('human_back_2.png', FLIP_H),
82 self._get_image('human_back_2.png', FLIP_H),
83 self._get_image('human_back_2.png', FLIP_H))),
[207]84 self.WOLF_FORM: render.AnimatedFacingImageRenderer(
[143]85 (self._get_image('werewolf_1.png'),
86 self._get_image('werewolf_1.png'),
87 self._get_image('werewolf_1.png'),
88 self._get_image('werewolf_2.png'),
89 self._get_image('werewolf_2.png'),
90 self._get_image('werewolf_2.png')),
91 (self._get_image('werewolf_1.png', FLIP_H),
92 self._get_image('werewolf_1.png', FLIP_H),
93 self._get_image('werewolf_1.png', FLIP_H),
94 self._get_image('werewolf_2.png', FLIP_H),
95 self._get_image('werewolf_2.png', FLIP_H),
96 self._get_image('werewolf_2.png', FLIP_H))),
[207]97 self.WOLF_FORM_BACK: render.AnimatedFacingImageRenderer(
[156]98 (self._get_image('werewolf_back_1.png'),
99 self._get_image('werewolf_back_1.png'),
100 self._get_image('werewolf_back_1.png'),
101 self._get_image('werewolf_back_2.png'),
102 self._get_image('werewolf_back_2.png'),
103 self._get_image('werewolf_back_2.png')),
104 (self._get_image('werewolf_back_1.png', FLIP_H),
105 self._get_image('werewolf_back_1.png', FLIP_H),
106 self._get_image('werewolf_back_1.png', FLIP_H),
107 self._get_image('werewolf_back_2.png', FLIP_H),
108 self._get_image('werewolf_back_2.png', FLIP_H),
109 self._get_image('werewolf_back_2.png', FLIP_H))),
[65]110 }
[123]111 for renderer in self._renderers.values():
112 renderer.set_game_object(self)
[65]113
[28]114 @classmethod
115 def from_saved_state(cls, saved_state):
116 """Create an instance from the provided serialised state.
117 """
118 obj = cls()
119 # TODO: Update from saved state.
120 return obj
121
[93]122 def get_render_angle(self):
123 return self.angle
124
[65]125 def go_werewolf(self):
[93]126 self._physicsers[self.form].remove_from_space()
[65]127 self.form = self.WOLF_FORM
[93]128 self._physicsers[self.form].add_to_space()
[200]129 self.physicser = self._physicsers[self.form]
[66]130 self._body.mass = 100
131 self._body.velocity_limit = 1000
[65]132 self.impulse_factor = 4000
[133]133 self._body.damping = 0.9
[156]134 if self.render_form == self.HUMAN_FORM:
135 self.render_form = self.WOLF_FORM
136 elif self.render_form == self.HUMAN_FORM_BACK:
137 self.render_form = self.WOLF_FORM_BACK
138 else:
139 self.render_form = self.WOLF_FORM
140 self.renderer = self._renderers[self.render_form]
[65]141
142 def go_human(self):
[93]143 self._physicsers[self.form].remove_from_space()
[65]144 self.form = self.HUMAN_FORM
[93]145 self._physicsers[self.form].add_to_space()
[200]146 self.physicser = self._physicsers[self.form]
[66]147 self._body.mass = 10
148 self._body.velocity_limit = 1000
[65]149 self.impulse_factor = 500
[133]150 self._body.damping = 0.8
[156]151 if self.render_form == self.WOLF_FORM:
152 self.render_form = self.HUMAN_FORM
153 elif self.render_form == self.WOLF_FORM_BACK:
154 self.render_form = self.HUMAN_FORM_BACK
155 else:
156 self.render_form = self.HUMAN_FORM
157 self.renderer = self._renderers[self.render_form]
158
159 def _switch_to_back(self):
160 if self.render_form == self.HUMAN_FORM:
161 self.render_form = self.HUMAN_FORM_BACK
162 elif self.render_form == self.WOLF_FORM:
163 self.render_form = self.WOLF_FORM_BACK
164 self.renderer = self._renderers[self.render_form]
165
166 def _switch_to_front(self):
167 if self.render_form == self.HUMAN_FORM_BACK:
168 self.render_form = self.HUMAN_FORM
169 elif self.render_form == self.WOLF_FORM_BACK:
170 self.render_form = self.WOLF_FORM
171 self.renderer = self._renderers[self.render_form]
[65]172
173 def set_direction(self, dx, dy):
174 if (dx, dy) == (0, 0):
[143]175 self.renderer.stop()
[65]176 return
[156]177 old_angle = self.angle
[93]178 self.angle = pymunk.Vec2d((dx, dy)).angle
[156]179 # If we've gone from quadrants 2 & 3 to 1 & 4 (or vice versa)
180 # switch between front & back views
181 if self.angle != math.pi:
182 # == math.pi is going straight left, which can't
183 # trigger a front/back swap and simplifies these checks
184 if self.angle > 0 and old_angle != self.angle:
185 self._switch_to_back()
186 elif self.angle < 0 and old_angle != self.angle:
187 self._switch_to_front()
[66]188 self._body.apply_impulse(
[65]189 (dx * self.impulse_factor, dy * self.impulse_factor))
[143]190 self.renderer.start()
[65]191
[179]192 def set_position(self, position):
193 self._body.position = position
194
195 def copy_state(self, old_protagonist):
196 self._physicsers[self.form].remove_from_space()
197 self._body.position = old_protagonist._body.position
198 self.form = old_protagonist.form
199 self.angle = old_protagonist.angle
200 self.render_form = old_protagonist.render_form
201 self.inventory = old_protagonist.inventory
202 self.renderer = self._renderers[self.render_form]
203 self._physicsers[self.form].add_to_space()
[200]204 self.physicser = self._physicsers[self.form]
[179]205
[65]206 def toggle_form(self):
207 if self.form == self.WOLF_FORM:
208 self.go_human()
209 else:
210 self.go_werewolf()
211
[28]212 def act_on(self, target):
213 """Perform an action on the target.
214 """
215 # TODO: Decide how best to do this.
216 pass
217
218 def attack(self):
219 """Attempt to hurt something.
220 """
221 pass
222
223 def in_wolf_form(self):
224 return self.form == self.WOLF_FORM
225
226 def in_human_form(self):
227 return self.form == self.HUMAN_FORM
228
229 def has_item(self, item):
230 return item in self.inventory
[73]231
232 def environmental_movement(self, dx, dy):
233 if (dx, dy) == (0, 0):
234 return
235 self._body.apply_impulse((dx, dy))
Note: See TracBrowser for help on using the repository browser.