# HG changeset patch # User Neil Muller # Date 1378495617 -7200 # Node ID 57895217bd7400b33d387797fc6bf7c30dfa3d76 # Parent ea315cdf286d6f24e5739fbb7e88cf7a87c11b53 Start refactoring alien movement diff -r ea315cdf286d -r 57895217bd74 nagslang/enemies.py --- a/nagslang/enemies.py Fri Sep 06 21:13:45 2013 +0200 +++ b/nagslang/enemies.py Fri Sep 06 21:26:57 2013 +0200 @@ -1,4 +1,5 @@ import math +import random import pymunk import pymunk.pygame_util @@ -105,6 +106,26 @@ COLLISION_TYPE_ENEMY) self._last_fired = self.lifetime + def greedy_move(self, target): + """Simple greedy path finder""" + def _calc_step(tp, pp): + if (tp < pp): + step = max(-1, tp - pp) + elif (tp > pp): + step = min(1, tp - pp) + if abs(step) < 0.5: + step = 0 + return step + x_step = _calc_step(target[0], self.physicser.position[0]) + y_step = _calc_step(target[1], self.physicser.position[1]) + return (x_step, y_step) + + def random_move(self): + """Random move""" + x_step = random.choice([-1, 0, 1]) + y_step = random.choice([-1, 0, 1]) + return x_step, y_step + class DeadEnemy(GameObject): def __init__(self, space, world, position, enemy_type='A'): @@ -169,20 +190,7 @@ target = self._end_pos else: target = self._start_pos - x_step = 0 - y_step = 0 - if (target[0] < self.physicser.position[0]): - x_step = max(-1, target[0] - self.physicser.position[0]) - elif (target[0] > self.physicser.position[0]): - x_step = min(1, target[0] - self.physicser.position[0]) - if abs(x_step) < 0.5: - x_step = 0 - if (target[1] < self.physicser.position[1]): - y_step = max(-1, target[1] - self.physicser.position[1]) - elif (target[1] > self.physicser.position[1]): - y_step = min(1, target[1] - self.physicser.position[1]) - if abs(y_step) < 0.5: - y_step = 0 + x_step, y_step = self.greedy_move(target) if abs(x_step) < 1 and abs(y_step) < 1: self._switch_direction() self.set_direction(x_step, y_step) @@ -226,19 +234,22 @@ else: return 'left' - def update(self, dt): - # Calculate the step every frame - # Distance to the protagonist - self.ranged_attack(300, ACID_SPEED, ACID_DAMAGE, 'acid', 0.2) + def _calc_movement(self): pos = self.physicser.position target = self.world.protagonist.get_shape().body.position if pos.get_distance(target) > self._range: # stop self.is_moving = False - return + return 0, 0 self.is_moving = True - dx = target.x - pos.x - dy = target.y - pos.y + dx, dy = self.greedy_move(target) + return dx, dy + + def update(self, dt): + # Calculate the step every frame + # Distance to the protagonist + self.ranged_attack(300, ACID_SPEED, ACID_DAMAGE, 'acid', 0.2) + dx, dy = self._calc_movement() self.set_direction(dx, dy) super(ChargingAlien, self).update(dt) @@ -246,3 +257,44 @@ def requires(cls): return [("name", "string"), ("position", "coordinates"), ("attack_range", "distance")] + + +class RunAndGunAlien(ChargingAlien): + # Simplistic shooter + # Move until we're in range, and then randomly + impulse_factor = 90 + is_moving = True + + def __init__(self, space, world, position, attack_range=100): + super(RunAndGunAlien, self).__init__(space, world, position, + attack_range) + self.count = 0 + self._old_move = (0, 0) + + def make_physics(self, space, position): + body = make_body(10, pymunk.inf, position, 0.8) + shape = pymunk.Circle(body, 30) + shape.elasticity = 1.0 + shape.friction = 0.05 + shape.collision_type = COLLISION_TYPE_ENEMY + return SingleShapePhysicser(space, shape) + + def _calc_movement(self): + pos = self.physicser.position + target = self.world.protagonist.get_shape().body.position + if pos.get_distance(target) < self._range: + if self.count > 10: + self._old_move = self.random_move() + self.count = 0 + return self._old_move + else: + return self.greedy_move(target) + + def update(self, dt): + super(RunAndGunAlien, self).update(dt) + self.count += 1 + + @classmethod + def requires(cls): + return [("name", "string"), ("position", "coordinates"), + ("attack_range", "distance")]