source: nagslang/protagonist.py@ 101:93aa745d57ff

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

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

File size: 4.9 KB
RevLine 
[65]1import pymunk
2import pymunk.pygame_util
3
[101]4import pygame
5
[81]6from nagslang.constants import COLLISION_TYPE_PLAYER
[65]7from nagslang.game_object import (
8 GameObject, SingleShapePhysicser, FacingImageRenderer)
[76]9from nagslang.mutators import FLIP_H
[101]10from nagslang.options import options
[65]11from nagslang.resources import resources
[28]12
13
[65]14class Protagonist(GameObject):
[28]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
[93]23 def __init__(self, space, position):
24 self._setup_physics(space, position)
[65]25 self._setup_renderers()
[28]26 self.inventory = {}
27 self.form = self.HUMAN_FORM
28
[65]29 super(Protagonist, self).__init__(
[93]30 self._physicsers[self.form], self._renderers[self.form])
[65]31
32 self.go_human()
33
[93]34 def _setup_physics(self, space, position):
35 self._body = pymunk.Body(10, pymunk.inf)
[66]36 self._body.position = position
37 self._body.velocity_func = self.velocity_func
[65]38
[93]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
[65]51
[66]52 def _get_image(self, name, *transforms):
53 return resources.get_image('creatures', name, transforms=transforms)
54
[65]55 def _setup_renderers(self):
56 self._renderers = {
57 self.HUMAN_FORM: FacingImageRenderer(
[76]58 self._get_image('human_1.png'),
59 self._get_image('human_1.png', FLIP_H)),
[65]60 self.WOLF_FORM: FacingImageRenderer(
[66]61 self._get_image('werewolf_1.png'),
62 self._get_image('werewolf_1.png', FLIP_H)),
[65]63 }
64
[28]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
[65]73 def velocity_func(self, body, gravity, damping, dt):
74 return pymunk.Body.update_velocity(body, gravity, self.damping, dt)
75
[93]76 def get_render_angle(self):
77 return self.angle
78
[65]79 def go_werewolf(self):
[93]80 self._physicsers[self.form].remove_from_space()
[65]81 self.form = self.WOLF_FORM
[93]82 self._physicsers[self.form].add_to_space()
[66]83 self._body.mass = 100
84 self._body.velocity_limit = 1000
[65]85 self.impulse_factor = 4000
86 self.damping = 0.9
87 self.renderer = self._renderers[self.form]
88
89 def go_human(self):
[93]90 self._physicsers[self.form].remove_from_space()
[65]91 self.form = self.HUMAN_FORM
[93]92 self._physicsers[self.form].add_to_space()
[66]93 self._body.mass = 10
94 self._body.velocity_limit = 1000
[65]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
[93]102 self.angle = pymunk.Vec2d((dx, dy)).angle
[66]103 self._body.apply_impulse(
[65]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
[28]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
[73]131
132 def environmental_movement(self, dx, dy):
133 if (dx, dy) == (0, 0):
134 return
135 self._body.apply_impulse((dx, dy))
[93]136
137 def render(self, surface):
[101]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)
[93]153 super(Protagonist, self).render(surface)
Note: See TracBrowser for help on using the repository browser.