1 | import pymunk
|
---|
2 | import pymunk.pygame_util
|
---|
3 |
|
---|
4 | from nagslang.constants import COLLISION_TYPE_PLAYER
|
---|
5 | from nagslang.game_object import (
|
---|
6 | GameObject, SingleShapePhysicser, FacingImageRenderer)
|
---|
7 | from nagslang.mutators import FLIP_H
|
---|
8 | from nagslang.resources import resources
|
---|
9 |
|
---|
10 |
|
---|
11 | class Protagonist(GameObject):
|
---|
12 | """Representation of our fearless protagonist.
|
---|
13 |
|
---|
14 | TODO: Factor out a bunch of this stuff when we need it for other objects.
|
---|
15 | """
|
---|
16 |
|
---|
17 | HUMAN_FORM = 'human'
|
---|
18 | WOLF_FORM = 'wolf'
|
---|
19 |
|
---|
20 | def __init__(self, position):
|
---|
21 | self._setup_physics(position)
|
---|
22 | self._setup_renderers()
|
---|
23 | self.inventory = {}
|
---|
24 | self.form = self.HUMAN_FORM
|
---|
25 |
|
---|
26 | super(Protagonist, self).__init__(
|
---|
27 | self._renderers[self.form], SingleShapePhysicser(self.shape))
|
---|
28 |
|
---|
29 | self.go_human()
|
---|
30 |
|
---|
31 | def _setup_physics(self, position):
|
---|
32 | self._body = pymunk.Body(10, 10000)
|
---|
33 | self._body.position = position
|
---|
34 | self._body.velocity_func = self.velocity_func
|
---|
35 |
|
---|
36 | self.shape = pymunk.Circle(self._body, 30)
|
---|
37 | self.shape.elasticity = 1.0
|
---|
38 | self.shape.friction = 10.0
|
---|
39 | self.shape.collision_type = COLLISION_TYPE_PLAYER
|
---|
40 |
|
---|
41 | def _get_image(self, name, *transforms):
|
---|
42 | return resources.get_image('creatures', name, transforms=transforms)
|
---|
43 |
|
---|
44 | def _setup_renderers(self):
|
---|
45 | self._renderers = {
|
---|
46 | self.HUMAN_FORM: FacingImageRenderer(
|
---|
47 | self._get_image('human_1.png'),
|
---|
48 | self._get_image('human_1.png', FLIP_H)),
|
---|
49 | self.WOLF_FORM: FacingImageRenderer(
|
---|
50 | self._get_image('werewolf_1.png'),
|
---|
51 | self._get_image('werewolf_1.png', FLIP_H)),
|
---|
52 | }
|
---|
53 |
|
---|
54 | @classmethod
|
---|
55 | def from_saved_state(cls, saved_state):
|
---|
56 | """Create an instance from the provided serialised state.
|
---|
57 | """
|
---|
58 | obj = cls()
|
---|
59 | # TODO: Update from saved state.
|
---|
60 | return obj
|
---|
61 |
|
---|
62 | def velocity_func(self, body, gravity, damping, dt):
|
---|
63 | return pymunk.Body.update_velocity(body, gravity, self.damping, dt)
|
---|
64 |
|
---|
65 | def go_werewolf(self):
|
---|
66 | self.form = self.WOLF_FORM
|
---|
67 | self._body.mass = 100
|
---|
68 | self._body.moment = 10000
|
---|
69 | self._body.velocity_limit = 1000
|
---|
70 | self.impulse_factor = 4000
|
---|
71 | self.damping = 0.9
|
---|
72 | self.renderer = self._renderers[self.form]
|
---|
73 |
|
---|
74 | def go_human(self):
|
---|
75 | self.form = self.HUMAN_FORM
|
---|
76 | self._body.mass = 10
|
---|
77 | self._body.moment = 1000
|
---|
78 | self._body.velocity_limit = 1000
|
---|
79 | self.impulse_factor = 500
|
---|
80 | self.damping = 0.8
|
---|
81 | self.renderer = self._renderers[self.form]
|
---|
82 |
|
---|
83 | def set_direction(self, dx, dy):
|
---|
84 | if (dx, dy) == (0, 0):
|
---|
85 | return
|
---|
86 | vec = pymunk.Vec2d((dx, dy))
|
---|
87 | self._body.angle = vec.angle
|
---|
88 | self._body.apply_impulse(
|
---|
89 | (dx * self.impulse_factor, dy * self.impulse_factor))
|
---|
90 |
|
---|
91 | def toggle_form(self):
|
---|
92 | if self.form == self.WOLF_FORM:
|
---|
93 | self.go_human()
|
---|
94 | else:
|
---|
95 | self.go_werewolf()
|
---|
96 |
|
---|
97 | def act_on(self, target):
|
---|
98 | """Perform an action on the target.
|
---|
99 | """
|
---|
100 | # TODO: Decide how best to do this.
|
---|
101 | pass
|
---|
102 |
|
---|
103 | def attack(self):
|
---|
104 | """Attempt to hurt something.
|
---|
105 | """
|
---|
106 | pass
|
---|
107 |
|
---|
108 | def in_wolf_form(self):
|
---|
109 | return self.form == self.WOLF_FORM
|
---|
110 |
|
---|
111 | def in_human_form(self):
|
---|
112 | return self.form == self.HUMAN_FORM
|
---|
113 |
|
---|
114 | def has_item(self, item):
|
---|
115 | return item in self.inventory
|
---|
116 |
|
---|
117 | def environmental_movement(self, dx, dy):
|
---|
118 | if (dx, dy) == (0, 0):
|
---|
119 | return
|
---|
120 | self._body.apply_impulse((dx, dy))
|
---|