changeset 186:d63c19003aec

Some refactoring and fixing, start of better collision handling.
author Jeremy Thurgood <firxen@gmail.com>
date Tue, 03 Sep 2013 20:06:12 +0200
parents dfacd08b8566
children 42a10c4f70c8
files nagslang/constants.py nagslang/events.py nagslang/game_object.py nagslang/tests/test_game_object.py nagslang/tests/test_level.py
diffstat 5 files changed, 50 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/nagslang/constants.py	Tue Sep 03 19:48:02 2013 +0200
+++ b/nagslang/constants.py	Tue Sep 03 20:06:12 2013 +0200
@@ -18,6 +18,15 @@
 
 SWITCH_PUSHERS = [COLLISION_TYPE_PLAYER, COLLISION_TYPE_BOX]
 
+CALLBACK_COLLIDERS = [
+    # Collisions between the player and shapes with these collision types will
+    # fire callbacks on the game object associated with the shape.
+    COLLISION_TYPE_SWITCH,
+    COLLISION_TYPE_BOX,
+    COLLISION_TYPE_ENEMY,
+    COLLISION_TYPE_DOOR,
+]
+
 ZORDER_FLOOR = 0
 ZORDER_LOW = 1
 ZORDER_MID = 2
--- a/nagslang/events.py	Tue Sep 03 19:48:02 2013 +0200
+++ b/nagslang/events.py	Tue Sep 03 20:06:12 2013 +0200
@@ -1,6 +1,7 @@
 """Events to post."""
 
 import pygame
+import pygame.locals
 
 
 class Event(object):
--- a/nagslang/game_object.py	Tue Sep 03 19:48:02 2013 +0200
+++ b/nagslang/game_object.py	Tue Sep 03 20:06:12 2013 +0200
@@ -41,6 +41,20 @@
         raise NotImplementedError()
 
 
+class YesPuzzler(Puzzler):
+    """Yes sir, I'm always on.
+    """
+    def get_state(self):
+        return True
+
+
+class NoPuzzler(Puzzler):
+    """No sir, I'm always off.
+    """
+    def get_state(self):
+        return False
+
+
 class CollidePuzzler(Puzzler):
     def __init__(self, *collision_types):
         if not collision_types:
@@ -107,6 +121,7 @@
     def __init__(self, space, shape):
         super(SingleShapePhysicser, self).__init__(space)
         self._shape = shape
+        shape.physicser = self
 
     def get_shape(self):
         return self._shape
@@ -341,6 +356,14 @@
     def animate(self):
         self.renderer.animate()
 
+    def collide_with_protagonist(self):
+        """Called as a `pre_solve` collision callback with the protagonist.
+
+        You can return `False` to ignore the collision, anything else
+        (including `None`) to process the collision as normal.
+        """
+        pass
+
 
 class FloorSwitch(GameObject):
     zorder = ZORDER_FLOOR
@@ -393,7 +416,7 @@
 class Door(GameObject):
     zorder = ZORDER_FLOOR
 
-    def __init__(self, space, position, destination, dest_pos):
+    def __init__(self, space, position, destination, dest_pos, key_state=None):
         body = make_body(pymunk.inf, pymunk.inf, position, damping=0.5)
         self.shape = pymunk.Poly(
             body, [(-32, -32), (32, -32), (32, 32), (-32, 32)])
@@ -401,9 +424,14 @@
         self.shape.sensor = True
         self.destination = destination
         self.dest_pos = tuple(dest_pos)
+        if key_state is None:
+            puzzler = YesPuzzler()
+        else:
+            puzzler = StateProxyPuzzler(key_state)
         super(Door, self).__init__(
             SingleShapePhysicser(space, self.shape),
             ImageRenderer(resources.get_image('objects', 'door.png')),
+            puzzler,
         )
 
     def animate(self):
--- a/nagslang/tests/test_game_object.py	Tue Sep 03 19:48:02 2013 +0200
+++ b/nagslang/tests/test_game_object.py	Tue Sep 03 20:06:12 2013 +0200
@@ -43,19 +43,21 @@
         puzzler.set_game_object(gobj)
         return puzzler
 
-    def assert_floor_switch(self, expected, shapes):
+    def assert_collide_state(self, expected, shapes, collision_types):
         gobj = FakeGameObject(None, FakeSpace(*shapes))
-        puzzler = self.mkpuzzler(gobj, game_object.FloorSwitchPuzzler)
+        puzzler = self.mkpuzzler(
+            gobj, game_object.CollidePuzzler, *collision_types)
         self.assertEqual(expected, puzzler.get_state())
 
-    def test_floor_switch_puzzler(self):
-        self.assert_floor_switch(False, [])
-        self.assert_floor_switch(False, [FakeShape()])
+    def test_collide_puzzler(self):
+        self.assert_collide_state(False, [], [])
+        self.assert_collide_state(False, [FakeShape()], SWITCH_PUSHERS)
 
         for collision_type in SWITCH_PUSHERS:
-            self.assert_floor_switch(True, [FakeShape(collision_type)])
-            self.assert_floor_switch(
-                True, [FakeShape(), FakeShape(collision_type)])
+            self.assert_collide_state(
+                True, [FakeShape(collision_type)], SWITCH_PUSHERS)
+            self.assert_collide_state(
+                True, [FakeShape(), FakeShape(collision_type)], SWITCH_PUSHERS)
 
     def test_state_proxy_puzzler(self):
         glue = game_object.PuzzleGlue()
--- a/nagslang/tests/test_level.py	Tue Sep 03 19:48:02 2013 +0200
+++ b/nagslang/tests/test_level.py	Tue Sep 03 20:06:12 2013 +0200
@@ -78,8 +78,7 @@
             self.assertTrue(
                 isinstance(puzzle_bits['foo_proxy'], go.StateProxyPuzzler))
             self.assertEqual('foo', puzzle_bits['foo_proxy']._state_source)
-            self.assertTrue(isinstance(puzzle_bits['foo'],
-                            go.FloorSwitchPuzzler))
+            self.assertTrue(isinstance(puzzle_bits['foo'], go.CollidePuzzler))
 
         level = self.make_level('foo', {
             'size': [5, 10],