changeset 172:bf144d817113

if year in range(1980, 1990): continue # how can we sleep while the kitsune is stuck to the floor?
author Simon Cross <hodgestar@gmail.com>
date Wed, 06 Apr 2011 01:35:20 +0200
parents 13e10b877f6c
children 21d34f1f15b2
files skaapsteker/physics.py skaapsteker/sprites/player.py
diffstat 2 files changed, 47 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/skaapsteker/physics.py	Wed Apr 06 01:04:43 2011 +0200
+++ b/skaapsteker/physics.py	Wed Apr 06 01:35:20 2011 +0200
@@ -30,7 +30,7 @@
     collision_layer = None # never collides with anything
     collides_with = set() # nothing collides with this
 
-    # set to True to have .update() called once per tick
+    # set to True to have .update() called once per tick (and have .collision_group set)
     wants_updates = False
 
     debug_color = (240, 0, 0)
@@ -46,6 +46,7 @@
         self.collide_rect = pygame.Rect(0, 0, 10, 10) # rectangle we use for collisions
         self.image = pygame.Surface((10, 10))
         self.image.fill((0, 0, 200))
+        self.collision_group = None
         self._mask_cache = {} # image id -> collision bit mask
 
     def init_pos(self):
@@ -133,6 +134,35 @@
     def update(self):
         pass # only called in wants_update = True
 
+    def check_collide_rect(self, new_collide_rect, new_rect, new_image):
+        if self.collision_group is None:
+            return True
+
+        # TODO: decide whether to throw out checking of existing
+        # collisions. Doesn't seem needed at the moment and takes
+        # time.
+        old_image = self.image
+        old_rect = self.rect
+        #rect_collides = self.collide_rect.colliderect
+        old_collisions = set()
+        #for other in self.collision_group:
+        #    if rect_collides(other.collide_rect) \
+        #       and self.check_collides(other):
+        #        old_collisions.add(other)
+
+        self.image = new_image
+        self.rect = new_rect
+        new_rect_collides = new_collide_rect.colliderect
+        new_collisions = set()
+        for other in self.collision_group:
+            if new_rect_collides(other.collide_rect) \
+               and self.check_collides(other):
+                new_collisions.add(other)
+
+        self.image = old_image
+        self.rect = old_rect
+        return not bool(new_collisions - old_collisions)
+
 
 class World(object):
 
@@ -165,6 +195,9 @@
         for layer in sprite.collides_with:
             self._add_collision_group(layer)
             self._collision_groups[layer].add(sprite)
+        if sprite.wants_updates:
+            self._updaters.add(sprite)
+            sprite.collision_group = self._collision_groups[sprite.collision_layer]
 
     def _add_collision_group(self, layer):
         if layer in self._collision_groups:
--- a/skaapsteker/sprites/player.py	Wed Apr 06 01:04:43 2011 +0200
+++ b/skaapsteker/sprites/player.py	Wed Apr 06 01:35:20 2011 +0200
@@ -22,7 +22,6 @@
         self.rect = None
         self._image_dict = {}
         self._animation_frame = 0.0
-        self._recent_collisions = []
         self._last_time = time.time()
         # State flags and such
         self.running = False
@@ -45,19 +44,21 @@
             cur_pos = self.collide_rect.midbottom
         else:
             cur_pos = (0, 0)
+
+        # TODO: can save a lot of calculation here by caching collision rects
         cand_image = images[int(self._animation_frame)]
-        cand_collide_rect = cand_image.get_bounding_rect(1)
+        cand_collide_rect = cand_image.get_bounding_rect(1).inflate(-2,-2)
+        cand_rect = cand_image.get_rect()
+        cand_rect_offset = cand_rect.centerx - cand_collide_rect.centerx, cand_rect.bottom - cand_collide_rect.bottom
+        cand_rect.midbottom = cur_pos[0] + cand_rect_offset[0], cur_pos[1] + cand_rect_offset[1]
         cand_collide_rect.midbottom = cur_pos
-        if cand_collide_rect.collidelist(self._recent_collisions) != -1 \
-                and self.collide_rect.collidelist(self._recent_collisions) == -1:
-            # We introduce a new collision, so don't update the image
+        if not self.check_collide_rect(cand_collide_rect, cand_rect, cand_image):
             return
-        self.image = images[int(self._animation_frame)]
-        self.collide_rect = self.image.get_bounding_rect(1)
-        self.rect = self.image.get_rect()
-        self.rect_offset = self.rect.centerx - self.collide_rect.centerx, self.rect.bottom - self.collide_rect.bottom
-        self.collide_rect.midbottom = cur_pos
-        self.rect.midbottom = cur_pos[0] + self.rect_offset[0], cur_pos[1] + self.rect_offset[1]
+
+        self.image = cand_image
+        self.collide_rect = cand_collide_rect
+        self.rect = cand_rect
+        self.rect_offset = cand_rect_offset
         self.init_pos()
 
     def update(self):
@@ -89,9 +90,7 @@
         self.facing = new_facing
 
     def collided(self, other):
-        self._recent_collisions.append(other.collide_rect)
-        while len(self._recent_collisions) > 10:
-            self._recent_collisions.pop(0)
+        pass
 
     def set_pos(self, pos):
         self.starting_tile_pos = pos