changeset 393:8d961e05b7b6

Use Result to handle firing
author Stefano Rivera <stefano@rivera.za.net>
date Sat, 07 Sep 2013 01:04:01 +0200
parents 1b7b0b8e8275
children 76f053cf2322
files nagslang/enemies.py nagslang/events.py nagslang/game_object.py nagslang/protagonist.py nagslang/screens/area.py
diffstat 5 files changed, 47 insertions(+), 44 deletions(-) [+]
line wrap: on
line diff
--- a/nagslang/enemies.py	Sat Sep 07 01:03:46 2013 +0200
+++ b/nagslang/enemies.py	Sat Sep 07 01:04:01 2013 +0200
@@ -8,9 +8,9 @@
 from nagslang import render
 from nagslang.constants import (COLLISION_TYPE_ENEMY, COLLISION_TYPE_FURNITURE,
                                 ACID_SPEED, ACID_DAMAGE, ZORDER_MID)
-from nagslang.events import FireEvent, EnemyDeathEvent
+from nagslang.events import EnemyDeathEvent
 from nagslang.game_object import (GameObject, SingleShapePhysicser, Result,
-                                  make_body)
+                                  Bullet, make_body)
 from nagslang.mutators import FLIP_H
 from nagslang.resources import resources
 from nagslang.utils import vec_with_length
@@ -85,7 +85,11 @@
     def collide_with_claw_attack(self, claw_attack):
         self.lose_health(claw_attack.damage)
 
-    def ranged_attack(self, range_, speed, damage, type_, reload_time):
+    def ranged_attack(self, range_, speed, damage, type_, reload_time,
+                      result=None):
+        if result is None:
+            result = Result()
+
         pos = self.physicser.position
         target = self.world.protagonist.get_shape().body.position
 
@@ -95,15 +99,16 @@
             if (shape in (self.get_shape(), self.world.protagonist.get_shape())
                     or shape.sensor):
                 continue
-            return
+            return result
 
         if not self.check_timer('reload_time'):
             self.start_timer('reload_time', reload_time)
             vec = Vec2d((target.x - pos.x, target.y - pos.y))
             if vec.length < range_:
                 vec.length = speed
-                FireEvent.post(pos, vec, damage, type_,
-                               COLLISION_TYPE_ENEMY)
+                result.add += (Bullet(self.get_space(), pos, vec, damage,
+                                      type_, COLLISION_TYPE_ENEMY),)
+        return result
 
     def greedy_move(self, target):
         """Simple greedy path finder"""
@@ -127,11 +132,13 @@
 
     def update(self, dt):
         super(Enemy, self).update(dt)
+        result = Result()
         if self.health <= 0:
-            return Result(
-                add=[DeadEnemy(self.get_space(), self.world,
-                               self.physicser.position, self.enemy_type)],
-                remove=[self])
+            result.remove += (self,)
+            result.add += (DeadEnemy(self.get_space(), self.world,
+                                     self.physicser.position,
+                                     self.enemy_type),)
+        return result
 
 
 class DeadEnemy(GameObject):
@@ -201,8 +208,8 @@
         if abs(x_step) < 1 and abs(y_step) < 1:
             self._switch_direction()
         self.set_direction(x_step, y_step)
-        self.ranged_attack(300, ACID_SPEED, ACID_DAMAGE, 'acid', 0.2)
-        return super(PatrollingAlien, self).update(dt)
+        result = self.ranged_attack(300, ACID_SPEED, ACID_DAMAGE, 'acid', 0.2)
+        return result.merge(super(PatrollingAlien, self).update(dt))
 
     @classmethod
     def requires(cls):
@@ -255,10 +262,10 @@
     def update(self, dt):
         # Calculate the step every frame
         # Distance to the protagonist
-        self.ranged_attack(300, ACID_SPEED, ACID_DAMAGE, 'acid', 0.2)
+        result = self.ranged_attack(300, ACID_SPEED, ACID_DAMAGE, 'acid', 0.2)
         dx, dy = self._calc_movement()
         self.set_direction(dx, dy)
-        return super(ChargingAlien, self).update(dt)
+        return result.merge(super(ChargingAlien, self).update(dt))
 
     @classmethod
     def requires(cls):
--- a/nagslang/events.py	Sat Sep 07 01:03:46 2013 +0200
+++ b/nagslang/events.py	Sat Sep 07 01:04:01 2013 +0200
@@ -46,14 +46,6 @@
         super(DoorEvent, cls).post(destination=destination, dest_pos=dest_pos)
 
 
-class FireEvent(UserEvent):
-    @classmethod
-    def post(cls, source, impulse, damage, bullet_type, source_collision_type):
-        super(FireEvent, cls).post(source=source, impulse=impulse,
-                                   damage=damage, bullet_type=bullet_type,
-                                   source_collision_type=source_collision_type)
-
-
 class EnemyDeathEvent(UserEvent):
     @classmethod
     def post(cls):
--- a/nagslang/game_object.py	Sat Sep 07 01:03:46 2013 +0200
+++ b/nagslang/game_object.py	Sat Sep 07 01:04:01 2013 +0200
@@ -24,6 +24,12 @@
         self.add = add
         self.remove = remove
 
+    def merge(self, result):
+        if result is not None:
+            self.add += result.add
+            self.remove += result.remove
+        return self
+
 
 def get_editable_game_objects():
     classes = []
--- a/nagslang/protagonist.py	Sat Sep 07 01:03:46 2013 +0200
+++ b/nagslang/protagonist.py	Sat Sep 07 01:04:01 2013 +0200
@@ -9,8 +9,9 @@
     PROTAGONIST_HEALTH_MIN_LEVEL, PROTAGONIST_HEALTH_MAX_LEVEL,
     NON_GAME_OBJECT_COLLIDERS, BULLET_DAMAGE, BULLET_SPEED, CLAW_DAMAGE,
     CMD_TOGGLE_FORM, CMD_ACTION)
-from nagslang.events import FireEvent, ClawEvent
-from nagslang.game_object import GameObject, Physicser, make_body
+from nagslang.events import ClawEvent
+from nagslang.game_object import (
+    GameObject, Physicser, Result, Bullet, make_body)
 from nagslang.mutators import FLIP_H
 from nagslang.resources import resources
 from nagslang.events import ScreenChange
@@ -192,7 +193,7 @@
             return
         self.start_timer('attack_cooldown')
         self.world.attacks += 1
-        self.attack()
+        return self.attack()
 
     def handle_keypress(self, key_command):
         if self.changing_sequence:
@@ -294,17 +295,17 @@
         """Attempt to hurt something.
         """
         if self.in_wolf_form():
-            self.claw()
+            return self.claw()
         else:
-            self.shoot()
+            return self.shoot()
 
     def shoot(self):
         if not self.has_item('gun'):
             return
         vec = vec_from_angle(self.angle, BULLET_SPEED)
-        FireEvent.post(
-            self.physicser.position, vec, BULLET_DAMAGE, 'bullet',
-            COLLISION_TYPE_PLAYER)
+        return Result(add=(Bullet(self.get_space(), self.physicser.position,
+                                  vec, BULLET_DAMAGE, 'bullet',
+                                  COLLISION_TYPE_PLAYER),))
 
     def claw(self):
         claw_range = (math.sqrt(math.pow(self.physicser.get_velocity()[0], 2) +
--- a/nagslang/screens/area.py	Sat Sep 07 01:03:46 2013 +0200
+++ b/nagslang/screens/area.py	Sat Sep 07 01:04:01 2013 +0200
@@ -8,11 +8,10 @@
     COLLISION_TYPE_WALL, COLLISION_TYPE_PLAYER, CALLBACK_COLLIDERS,
     COLLISION_TYPE_FURNITURE, COLLISION_TYPE_WEREWOLF_ATTACK,
     CMD_TOGGLE_FORM, CMD_ACTION)
-from nagslang.events import (
-    ScreenChange, DoorEvent, EnemyDeathEvent, FireEvent, ClawEvent)
+from nagslang.events import ScreenChange, DoorEvent, EnemyDeathEvent, ClawEvent
 from nagslang.level import Level
 from nagslang.screens.base import Screen
-from nagslang.game_object import Bullet, ClawAttack
+from nagslang.game_object import ClawAttack
 from nagslang.sound import sound
 
 
@@ -178,10 +177,6 @@
                 return
             # else we're teleporting within the screen, and just the
             # position change is enough
-        elif FireEvent.matches(ev):
-            bullet = Bullet(self.space, ev.source, ev.impulse, ev.damage,
-                            ev.bullet_type, ev.source_collision_type)
-            self._drawables.add(bullet)
         elif EnemyDeathEvent.matches(ev):
             self.world.kills += 1
         elif ClawEvent.matches(ev):
@@ -233,18 +228,20 @@
         dx, dy = self.keys.get_direction()
         self.protagonist.set_direction(dx, dy)
         if self.keys.is_attacking():
-            self.protagonist.handle_attack_key_down()
+            self._handle_result(self.protagonist.handle_attack_key_down())
 
     def tick(self, seconds):
         super(AreaScreen, self).tick(seconds)
         self.tick_protagonist()
         for drawable in self._drawables:
-            result = drawable.update(seconds)
-            if result is not None:
-                for new_drawable in result.add:
-                    self._drawables.add(new_drawable)
-                for old_drawable in result.remove:
-                    self._drawables.remove(old_drawable)
+            self._handle_result(drawable.update(seconds))
+
+    def _handle_result(self, result):
+        if result is not None:
+            for drawable in result.add:
+                self._drawables.add(drawable)
+            for drawable in result.remove:
+                self._drawables.remove(drawable)
 
     def render_health_bar(self, surface, damage_experienced=None):
         bar_surface = pygame.Surface((110, 50)).convert(surface)