changeset 368:57895217bd74

Start refactoring alien movement
author Neil Muller <drnlmuller@gmail.com>
date Fri, 06 Sep 2013 21:26:57 +0200
parents ea315cdf286d
children aa889ffa3295
files nagslang/enemies.py
diffstat 1 files changed, 73 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- 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")]