Mercurial > nagslang
annotate nagslang/enemies.py @ 277:56e42c00da25
Protagonist and enemies should see the world
author | Neil Muller <drnlmuller@gmail.com> |
---|---|
date | Thu, 05 Sep 2013 13:15:31 +0200 |
parents | 8a695b8ecd6c |
children | e72025e9aa07 |
rev | line source |
---|---|
229
329b3044ddef
Much better facing renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
218
diff
changeset
|
1 import math |
329b3044ddef
Much better facing renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
218
diff
changeset
|
2 |
168 | 3 import pymunk |
4 import pymunk.pygame_util | |
5 | |
207 | 6 from nagslang import render |
168 | 7 from nagslang.constants import COLLISION_TYPE_ENEMY, ZORDER_MID |
207 | 8 from nagslang.game_object import GameObject, SingleShapePhysicser, make_body |
168 | 9 from nagslang.mutators import FLIP_H |
10 from nagslang.resources import resources | |
11 | |
12 | |
235
831e4f6b3d18
Add hints for the level editor
Neil Muller <drnlmuller@gmail.com>
parents:
229
diff
changeset
|
13 def get_editable_enemies(): |
831e4f6b3d18
Add hints for the level editor
Neil Muller <drnlmuller@gmail.com>
parents:
229
diff
changeset
|
14 classes = [] |
831e4f6b3d18
Add hints for the level editor
Neil Muller <drnlmuller@gmail.com>
parents:
229
diff
changeset
|
15 for cls_name, cls in globals().iteritems(): |
831e4f6b3d18
Add hints for the level editor
Neil Muller <drnlmuller@gmail.com>
parents:
229
diff
changeset
|
16 if isinstance(cls, type) and issubclass(cls, Enemy): |
831e4f6b3d18
Add hints for the level editor
Neil Muller <drnlmuller@gmail.com>
parents:
229
diff
changeset
|
17 if hasattr(cls, 'requires'): |
831e4f6b3d18
Add hints for the level editor
Neil Muller <drnlmuller@gmail.com>
parents:
229
diff
changeset
|
18 classes.append((cls_name, cls)) |
831e4f6b3d18
Add hints for the level editor
Neil Muller <drnlmuller@gmail.com>
parents:
229
diff
changeset
|
19 return classes |
831e4f6b3d18
Add hints for the level editor
Neil Muller <drnlmuller@gmail.com>
parents:
229
diff
changeset
|
20 |
831e4f6b3d18
Add hints for the level editor
Neil Muller <drnlmuller@gmail.com>
parents:
229
diff
changeset
|
21 |
168 | 22 class Enemy(GameObject): |
23 """A base class for mobile enemies""" | |
24 | |
277
56e42c00da25
Protagonist and enemies should see the world
Neil Muller <drnlmuller@gmail.com>
parents:
265
diff
changeset
|
25 def __init__(self, space, world, position): |
168 | 26 self._setup_physics(space, position) |
27 self._setup_renderer() | |
28 | |
29 super(Enemy, self).__init__( | |
30 self._physicser, self.renderer) | |
31 self.zorder = ZORDER_MID | |
277
56e42c00da25
Protagonist and enemies should see the world
Neil Muller <drnlmuller@gmail.com>
parents:
265
diff
changeset
|
32 self.world = world |
168 | 33 |
34 def _get_image(self, name, *transforms): | |
35 return resources.get_image('creatures', name, transforms=transforms) | |
36 | |
37 def _setup_physics(self, space, position): | |
38 raise NotImplementedError | |
39 | |
40 def _setup_renderer(self): | |
41 raise NotImplementedError | |
42 | |
43 def attack(self): | |
44 raise NotImplementedError | |
45 | |
235
831e4f6b3d18
Add hints for the level editor
Neil Muller <drnlmuller@gmail.com>
parents:
229
diff
changeset
|
46 @classmethod |
831e4f6b3d18
Add hints for the level editor
Neil Muller <drnlmuller@gmail.com>
parents:
229
diff
changeset
|
47 def requires(cls): |
831e4f6b3d18
Add hints for the level editor
Neil Muller <drnlmuller@gmail.com>
parents:
229
diff
changeset
|
48 return [("name", "string"), ("position", "coordinates")] |
831e4f6b3d18
Add hints for the level editor
Neil Muller <drnlmuller@gmail.com>
parents:
229
diff
changeset
|
49 |
168 | 50 |
51 class PatrollingAlien(Enemy): | |
218
9e2ef2f15035
Better rendering and movement detection.
Jeremy Thurgood <firxen@gmail.com>
parents:
217
diff
changeset
|
52 is_moving = True # Always walking. |
168 | 53 |
277
56e42c00da25
Protagonist and enemies should see the world
Neil Muller <drnlmuller@gmail.com>
parents:
265
diff
changeset
|
54 def __init__(self, space, world, position, end_position): |
168 | 55 # An enemy that patrols between the two points |
277
56e42c00da25
Protagonist and enemies should see the world
Neil Muller <drnlmuller@gmail.com>
parents:
265
diff
changeset
|
56 super(PatrollingAlien, self).__init__(space, world, position) |
168 | 57 self._start_pos = position |
58 self._end_pos = end_position | |
59 self._direction = 'away' | |
60 | |
61 def _setup_physics(self, space, position): | |
208
3d54fe7a2998
Fun with mass and friction.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
62 self._body = make_body(10, pymunk.inf, position, 0.8) |
168 | 63 |
64 self._shape = pymunk.Circle(self._body, 30) | |
65 | |
66 self._shape.elasticity = 1.0 | |
208
3d54fe7a2998
Fun with mass and friction.
Jeremy Thurgood <firxen@gmail.com>
parents:
207
diff
changeset
|
67 self._shape.friction = 0.05 |
168 | 68 self._shape.collision_type = COLLISION_TYPE_ENEMY |
69 self._physicser = SingleShapePhysicser(space, self._shape) | |
70 self.impulse_factor = 50 | |
71 self.angle = 0 | |
72 | |
73 def _setup_renderer(self): | |
217
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
208
diff
changeset
|
74 self.renderer = render.FacingSelectionRenderer({ |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
208
diff
changeset
|
75 'left': render.TimedAnimatedRenderer( |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
208
diff
changeset
|
76 [self._get_image('alien_A_1.png'), |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
208
diff
changeset
|
77 self._get_image('alien_A_2.png')], 3), |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
208
diff
changeset
|
78 'right': render.TimedAnimatedRenderer( |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
208
diff
changeset
|
79 [self._get_image('alien_A_1.png', FLIP_H), |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
208
diff
changeset
|
80 self._get_image('alien_A_2.png', FLIP_H)], 3), |
d98daba73055
Composition-based renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
208
diff
changeset
|
81 }) |
168 | 82 |
83 def get_render_angle(self): | |
229
329b3044ddef
Much better facing renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
218
diff
changeset
|
84 # No image rotation when rendering, please. |
329b3044ddef
Much better facing renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
218
diff
changeset
|
85 return 0 |
329b3044ddef
Much better facing renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
218
diff
changeset
|
86 |
329b3044ddef
Much better facing renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
218
diff
changeset
|
87 def get_facing_direction(self): |
329b3044ddef
Much better facing renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
218
diff
changeset
|
88 # Enemies can face left or right. |
329b3044ddef
Much better facing renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
218
diff
changeset
|
89 if - math.pi / 2 < self.angle <= math.pi / 2: |
329b3044ddef
Much better facing renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
218
diff
changeset
|
90 return 'right' |
329b3044ddef
Much better facing renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
218
diff
changeset
|
91 else: |
329b3044ddef
Much better facing renderers.
Jeremy Thurgood <firxen@gmail.com>
parents:
218
diff
changeset
|
92 return 'left' |
168 | 93 |
94 def _switch_direction(self): | |
95 if self._direction == 'away': | |
96 self._direction = 'towards' | |
97 else: | |
98 self._direction = 'away' | |
99 | |
100 def set_direction(self, dx, dy): | |
101 self.angle = pymunk.Vec2d((dx, dy)).angle | |
102 self._body.apply_impulse( | |
103 (dx * self.impulse_factor, dy * self.impulse_factor)) | |
104 | |
105 def animate(self): | |
106 # Calculate the step every frame | |
107 if self._direction == 'away': | |
108 target = self._end_pos | |
109 else: | |
110 target = self._start_pos | |
111 x_step = 0 | |
112 y_step = 0 | |
113 if (target[0] < self._body.position[0]): | |
114 x_step = max(-1, target[0] - self._body.position[0]) | |
115 elif (target[0] > self._body.position[0]): | |
116 x_step = min(1, target[0] - self._body.position[0]) | |
117 if abs(x_step) < 0.5: | |
118 x_step = 0 | |
119 if (target[1] < self._body.position[1]): | |
120 y_step = max(-1, target[1] - self._body.position[1]) | |
121 elif (target[1] > self._body.position[1]): | |
122 y_step = min(1, target[1] - self._body.position[1]) | |
123 if abs(y_step) < 0.5: | |
124 y_step = 0 | |
125 if abs(x_step) < 1 and abs(y_step) < 1: | |
126 self._switch_direction() | |
127 self.set_direction(x_step, y_step) | |
128 super(PatrollingAlien, self).animate() | |
235
831e4f6b3d18
Add hints for the level editor
Neil Muller <drnlmuller@gmail.com>
parents:
229
diff
changeset
|
129 |
259 | 130 def collide_with_protagonist(self, protagonist): |
265 | 131 protagonist.lose_health(15) |
258 | 132 |
235
831e4f6b3d18
Add hints for the level editor
Neil Muller <drnlmuller@gmail.com>
parents:
229
diff
changeset
|
133 @classmethod |
831e4f6b3d18
Add hints for the level editor
Neil Muller <drnlmuller@gmail.com>
parents:
229
diff
changeset
|
134 def requires(cls): |
831e4f6b3d18
Add hints for the level editor
Neil Muller <drnlmuller@gmail.com>
parents:
229
diff
changeset
|
135 return [("name", "string"), ("position", "coordinates"), |
831e4f6b3d18
Add hints for the level editor
Neil Muller <drnlmuller@gmail.com>
parents:
229
diff
changeset
|
136 ("end_position", "coordinates")] |