source: nagslang/protagonist.py@ 103:adf3cd83bf7a

Last change on this file since 103:adf3cd83bf7a was 101:93aa745d57ff, checked in by Neil Muller <drnlmuller@…>, 8 years ago

draw protagnist bounding box in debug mode. Redo drawing logic to avoid pymunk noise

File size: 4.9 KB
Line 
1import pymunk
2import pymunk.pygame_util
3
4import pygame
5
6from nagslang.constants import COLLISION_TYPE_PLAYER
7from nagslang.game_object import (
8 GameObject, SingleShapePhysicser, FacingImageRenderer)
9from nagslang.mutators import FLIP_H
10from nagslang.options import options
11from nagslang.resources import resources
12
13
14class Protagonist(GameObject):
15 """Representation of our fearless protagonist.
16
17 TODO: Factor out a bunch of this stuff when we need it for other objects.
18 """
19
20 HUMAN_FORM = 'human'
21 WOLF_FORM = 'wolf'
22
23 def __init__(self, space, position):
24 self._setup_physics(space, position)
25 self._setup_renderers()
26 self.inventory = {}
27 self.form = self.HUMAN_FORM
28
29 super(Protagonist, self).__init__(
30 self._physicsers[self.form], self._renderers[self.form])
31
32 self.go_human()
33
34 def _setup_physics(self, space, position):
35 self._body = pymunk.Body(10, pymunk.inf)
36 self._body.position = position
37 self._body.velocity_func = self.velocity_func
38
39 self._shapes = {
40 self.HUMAN_FORM: pymunk.Poly(
41 self._body, [(-15, -30), (15, -30), (15, 30), (-15, 30)]),
42 self.WOLF_FORM: pymunk.Circle(self._body, 30),
43 }
44 self._physicsers = {}
45 for form, shape in self._shapes.iteritems():
46 shape.elasticity = 1.0
47 shape.friction = 10.0
48 shape.collision_type = COLLISION_TYPE_PLAYER
49 self._physicsers[form] = SingleShapePhysicser(space, shape)
50 self.angle = 0
51
52 def _get_image(self, name, *transforms):
53 return resources.get_image('creatures', name, transforms=transforms)
54
55 def _setup_renderers(self):
56 self._renderers = {
57 self.HUMAN_FORM: FacingImageRenderer(
58 self._get_image('human_1.png'),
59 self._get_image('human_1.png', FLIP_H)),
60 self.WOLF_FORM: FacingImageRenderer(
61 self._get_image('werewolf_1.png'),
62 self._get_image('werewolf_1.png', FLIP_H)),
63 }
64
65 @classmethod
66 def from_saved_state(cls, saved_state):
67 """Create an instance from the provided serialised state.
68 """
69 obj = cls()
70 # TODO: Update from saved state.
71 return obj
72
73 def velocity_func(self, body, gravity, damping, dt):
74 return pymunk.Body.update_velocity(body, gravity, self.damping, dt)
75
76 def get_render_angle(self):
77 return self.angle
78
79 def go_werewolf(self):
80 self._physicsers[self.form].remove_from_space()
81 self.form = self.WOLF_FORM
82 self._physicsers[self.form].add_to_space()
83 self._body.mass = 100
84 self._body.velocity_limit = 1000
85 self.impulse_factor = 4000
86 self.damping = 0.9
87 self.renderer = self._renderers[self.form]
88
89 def go_human(self):
90 self._physicsers[self.form].remove_from_space()
91 self.form = self.HUMAN_FORM
92 self._physicsers[self.form].add_to_space()
93 self._body.mass = 10
94 self._body.velocity_limit = 1000
95 self.impulse_factor = 500
96 self.damping = 0.8
97 self.renderer = self._renderers[self.form]
98
99 def set_direction(self, dx, dy):
100 if (dx, dy) == (0, 0):
101 return
102 self.angle = pymunk.Vec2d((dx, dy)).angle
103 self._body.apply_impulse(
104 (dx * self.impulse_factor, dy * self.impulse_factor))
105
106 def toggle_form(self):
107 if self.form == self.WOLF_FORM:
108 self.go_human()
109 else:
110 self.go_werewolf()
111
112 def act_on(self, target):
113 """Perform an action on the target.
114 """
115 # TODO: Decide how best to do this.
116 pass
117
118 def attack(self):
119 """Attempt to hurt something.
120 """
121 pass
122
123 def in_wolf_form(self):
124 return self.form == self.WOLF_FORM
125
126 def in_human_form(self):
127 return self.form == self.HUMAN_FORM
128
129 def has_item(self, item):
130 return item in self.inventory
131
132 def environmental_movement(self, dx, dy):
133 if (dx, dy) == (0, 0):
134 return
135 self._body.apply_impulse((dx, dy))
136
137 def render(self, surface):
138 if options.debug:
139 # Less general that pymunk.pygame_utils.draw, but also a
140 # lot less noisy
141 color = pygame.color.THECOLORS['lightblue']
142 if hasattr(self._shapes[self.form], 'get_vertices'):
143 # polygon bounding box
144 points = [pymunk.pygame_util.to_pygame(p, surface)
145 for p in self._shapes[self.form].get_vertices()]
146 pygame.draw.lines(surface, color, True, points, 2)
147 else:
148 # draw the circle
149 centre = pymunk.pygame_util.to_pygame(
150 self._shapes[self.form].body.position, surface)
151 radius = int(self._shapes[self.form].radius)
152 pygame.draw.circle(surface, color, centre, radius, 2)
153 super(Protagonist, self).render(surface)
Note: See TracBrowser for help on using the repository browser.