[168] | 1 | import pymunk
|
---|
| 2 | import pymunk.pygame_util
|
---|
| 3 |
|
---|
| 4 | from nagslang.constants import COLLISION_TYPE_ENEMY, ZORDER_MID
|
---|
| 5 | from nagslang.game_object import (
|
---|
| 6 | GameObject, SingleShapePhysicser, AnimatedFacingImageRenderer, make_body)
|
---|
| 7 | from nagslang.mutators import FLIP_H
|
---|
| 8 | from nagslang.resources import resources
|
---|
| 9 |
|
---|
| 10 |
|
---|
| 11 | class Enemy(GameObject):
|
---|
| 12 | """A base class for mobile enemies"""
|
---|
| 13 |
|
---|
| 14 | def __init__(self, space, position):
|
---|
| 15 | self._setup_physics(space, position)
|
---|
| 16 | self._setup_renderer()
|
---|
| 17 |
|
---|
| 18 | super(Enemy, self).__init__(
|
---|
| 19 | self._physicser, self.renderer)
|
---|
| 20 | self.zorder = ZORDER_MID
|
---|
| 21 |
|
---|
| 22 | def _get_image(self, name, *transforms):
|
---|
| 23 | return resources.get_image('creatures', name, transforms=transforms)
|
---|
| 24 |
|
---|
| 25 | def _setup_physics(self, space, position):
|
---|
| 26 | raise NotImplementedError
|
---|
| 27 |
|
---|
| 28 | def _setup_renderer(self):
|
---|
| 29 | raise NotImplementedError
|
---|
| 30 |
|
---|
| 31 | def attack(self):
|
---|
| 32 | raise NotImplementedError
|
---|
| 33 |
|
---|
| 34 |
|
---|
| 35 | class PatrollingAlien(Enemy):
|
---|
| 36 |
|
---|
| 37 | def __init__(self, space, position, end_position):
|
---|
| 38 | # An enemy that patrols between the two points
|
---|
| 39 | super(PatrollingAlien, self).__init__(space, position)
|
---|
| 40 | self._start_pos = position
|
---|
| 41 | self._end_pos = end_position
|
---|
| 42 | self._direction = 'away'
|
---|
| 43 |
|
---|
| 44 | def _setup_physics(self, space, position):
|
---|
| 45 | self._body = make_body(5, pymunk.inf, position, 0.8)
|
---|
| 46 |
|
---|
| 47 | self._shape = pymunk.Circle(self._body, 30)
|
---|
| 48 |
|
---|
| 49 | self._shape.elasticity = 1.0
|
---|
| 50 | self._shape.friction = 10.0
|
---|
| 51 | self._shape.collision_type = COLLISION_TYPE_ENEMY
|
---|
| 52 | self._physicser = SingleShapePhysicser(space, self._shape)
|
---|
| 53 | self.impulse_factor = 50
|
---|
| 54 | self.angle = 0
|
---|
| 55 |
|
---|
| 56 | def _setup_renderer(self):
|
---|
| 57 | self.renderer = AnimatedFacingImageRenderer(
|
---|
| 58 | (self._get_image('alien_A_1.png'),
|
---|
| 59 | self._get_image('alien_A_1.png'),
|
---|
| 60 | self._get_image('alien_A_1.png'),
|
---|
| 61 | self._get_image('alien_A_1.png'),
|
---|
| 62 | self._get_image('alien_A_1.png'),
|
---|
| 63 | self._get_image('alien_A_1.png'),
|
---|
| 64 | self._get_image('alien_A_2.png'),
|
---|
| 65 | self._get_image('alien_A_2.png'),
|
---|
| 66 | self._get_image('alien_A_2.png')),
|
---|
| 67 | (self._get_image('alien_A_1.png', FLIP_H),
|
---|
| 68 | self._get_image('alien_A_1.png', FLIP_H),
|
---|
| 69 | self._get_image('alien_A_1.png', FLIP_H),
|
---|
| 70 | self._get_image('alien_A_1.png', FLIP_H),
|
---|
| 71 | self._get_image('alien_A_1.png', FLIP_H),
|
---|
| 72 | self._get_image('alien_A_1.png', FLIP_H),
|
---|
| 73 | self._get_image('alien_A_2.png', FLIP_H),
|
---|
| 74 | self._get_image('alien_A_2.png', FLIP_H),
|
---|
| 75 | self._get_image('alien_A_2.png', FLIP_H)))
|
---|
| 76 | # We're always animated
|
---|
| 77 | self.renderer.start()
|
---|
| 78 |
|
---|
| 79 | def get_render_angle(self):
|
---|
| 80 | return self.angle
|
---|
| 81 |
|
---|
| 82 | def _switch_direction(self):
|
---|
| 83 | if self._direction == 'away':
|
---|
| 84 | self._direction = 'towards'
|
---|
| 85 | else:
|
---|
| 86 | self._direction = 'away'
|
---|
| 87 |
|
---|
| 88 | def set_direction(self, dx, dy):
|
---|
| 89 | self.angle = pymunk.Vec2d((dx, dy)).angle
|
---|
| 90 | self._body.apply_impulse(
|
---|
| 91 | (dx * self.impulse_factor, dy * self.impulse_factor))
|
---|
| 92 |
|
---|
| 93 | def animate(self):
|
---|
| 94 | # Calculate the step every frame
|
---|
| 95 | if self._direction == 'away':
|
---|
| 96 | target = self._end_pos
|
---|
| 97 | else:
|
---|
| 98 | target = self._start_pos
|
---|
| 99 | x_step = 0
|
---|
| 100 | y_step = 0
|
---|
| 101 | if (target[0] < self._body.position[0]):
|
---|
| 102 | x_step = max(-1, target[0] - self._body.position[0])
|
---|
| 103 | elif (target[0] > self._body.position[0]):
|
---|
| 104 | x_step = min(1, target[0] - self._body.position[0])
|
---|
| 105 | if abs(x_step) < 0.5:
|
---|
| 106 | x_step = 0
|
---|
| 107 | if (target[1] < self._body.position[1]):
|
---|
| 108 | y_step = max(-1, target[1] - self._body.position[1])
|
---|
| 109 | elif (target[1] > self._body.position[1]):
|
---|
| 110 | y_step = min(1, target[1] - self._body.position[1])
|
---|
| 111 | if abs(y_step) < 0.5:
|
---|
| 112 | y_step = 0
|
---|
| 113 | if abs(x_step) < 1 and abs(y_step) < 1:
|
---|
| 114 | self._switch_direction()
|
---|
| 115 | self.set_direction(x_step, y_step)
|
---|
| 116 | super(PatrollingAlien, self).animate()
|
---|