Mercurial > nagslang
view nagslang/enemies.py @ 265:8a695b8ecd6c
Correcting damage application
author | David Sharpe |
---|---|
date | Thu, 05 Sep 2013 00:37:48 +0200 |
parents | f23be1013c94 |
children | 56e42c00da25 |
line wrap: on
line source
import math import pymunk import pymunk.pygame_util from nagslang import render from nagslang.constants import COLLISION_TYPE_ENEMY, ZORDER_MID from nagslang.game_object import GameObject, SingleShapePhysicser, make_body from nagslang.mutators import FLIP_H from nagslang.resources import resources def get_editable_enemies(): classes = [] for cls_name, cls in globals().iteritems(): if isinstance(cls, type) and issubclass(cls, Enemy): if hasattr(cls, 'requires'): classes.append((cls_name, cls)) return classes class Enemy(GameObject): """A base class for mobile enemies""" def __init__(self, space, position): self._setup_physics(space, position) self._setup_renderer() super(Enemy, self).__init__( self._physicser, self.renderer) self.zorder = ZORDER_MID def _get_image(self, name, *transforms): return resources.get_image('creatures', name, transforms=transforms) def _setup_physics(self, space, position): raise NotImplementedError def _setup_renderer(self): raise NotImplementedError def attack(self): raise NotImplementedError @classmethod def requires(cls): return [("name", "string"), ("position", "coordinates")] class PatrollingAlien(Enemy): is_moving = True # Always walking. def __init__(self, space, position, end_position): # An enemy that patrols between the two points super(PatrollingAlien, self).__init__(space, position) self._start_pos = position self._end_pos = end_position self._direction = 'away' def _setup_physics(self, space, position): self._body = make_body(10, pymunk.inf, position, 0.8) self._shape = pymunk.Circle(self._body, 30) self._shape.elasticity = 1.0 self._shape.friction = 0.05 self._shape.collision_type = COLLISION_TYPE_ENEMY self._physicser = SingleShapePhysicser(space, self._shape) self.impulse_factor = 50 self.angle = 0 def _setup_renderer(self): self.renderer = render.FacingSelectionRenderer({ 'left': render.TimedAnimatedRenderer( [self._get_image('alien_A_1.png'), self._get_image('alien_A_2.png')], 3), 'right': render.TimedAnimatedRenderer( [self._get_image('alien_A_1.png', FLIP_H), self._get_image('alien_A_2.png', FLIP_H)], 3), }) def get_render_angle(self): # No image rotation when rendering, please. return 0 def get_facing_direction(self): # Enemies can face left or right. if - math.pi / 2 < self.angle <= math.pi / 2: return 'right' else: return 'left' def _switch_direction(self): if self._direction == 'away': self._direction = 'towards' else: self._direction = 'away' def set_direction(self, dx, dy): self.angle = pymunk.Vec2d((dx, dy)).angle self._body.apply_impulse( (dx * self.impulse_factor, dy * self.impulse_factor)) def animate(self): # Calculate the step every frame if self._direction == 'away': target = self._end_pos else: target = self._start_pos x_step = 0 y_step = 0 if (target[0] < self._body.position[0]): x_step = max(-1, target[0] - self._body.position[0]) elif (target[0] > self._body.position[0]): x_step = min(1, target[0] - self._body.position[0]) if abs(x_step) < 0.5: x_step = 0 if (target[1] < self._body.position[1]): y_step = max(-1, target[1] - self._body.position[1]) elif (target[1] > self._body.position[1]): y_step = min(1, target[1] - self._body.position[1]) if abs(y_step) < 0.5: y_step = 0 if abs(x_step) < 1 and abs(y_step) < 1: self._switch_direction() self.set_direction(x_step, y_step) super(PatrollingAlien, self).animate() def collide_with_protagonist(self, protagonist): protagonist.lose_health(15) @classmethod def requires(cls): return [("name", "string"), ("position", "coordinates"), ("end_position", "coordinates")]