Bug 562: Collision detection for unisolid tiles doesn't handle tilemap offset
authorFlorian Forster <supertux@octo.it>
Sat, 30 Jan 2010 17:36:43 +0000 (17:36 +0000)
committerFlorian Forster <supertux@octo.it>
Sat, 30 Jan 2010 17:36:43 +0000 (17:36 +0000)
- Use the new TileMap::get_tile_bbox function, which handles offset.

Cleanups:

- Get the bottom from the original MovingObject rather than subtracting
  movement from dest (an ugly kludge).

- Apply De Morgan's law so the test more clearly corresponds to the
  comment.

Resolves #562. Thanks to Matt McCutchen for updating the patch.

SVN-Revision: 6299

src/supertux/sector.cpp
src/supertux/sector.hpp

index 8c96095..f0387f6 100644 (file)
@@ -954,7 +954,8 @@ void check_collisions(collision::Constraints* constraints,
 
 void
 Sector::collision_tilemap(collision::Constraints* constraints,
-                          const Vector& movement, const Rectf& dest) const
+                          const Vector& movement, const Rectf& dest,
+                          MovingObject& object) const
 {
   // calculate rectangle where the object will move
   float x1 = dest.get_left();
@@ -976,14 +977,15 @@ Sector::collision_tilemap(collision::Constraints* constraints,
         // skip non-solid tiles
         if((tile->getAttributes() & Tile::SOLID) == 0)
           continue;
+        Rectf rect = solids->get_tile_bbox(x, y);
+
         // only handle unisolid when the player is falling down and when he was
         // above the tile before
         if(tile->getAttributes() & Tile::UNISOLID) {
-          if(movement.y <= 0 || dest.get_bottom() - movement.y - SHIFT_DELTA > y*32)
+          if(!(movement.y > 0 && object.get_bbox().get_bottom() - SHIFT_DELTA <= rect.get_top()))
             continue;
         }
 
-        Rectf rect = solids->get_tile_bbox(x, y);
         if(tile->getAttributes() & Tile::SLOPE) { // slope tile
           AATriangle triangle;
           int slope_data = tile->getData();
@@ -1110,9 +1112,9 @@ Sector::collision_object(MovingObject* object1, MovingObject* object2) const
 void
 Sector::collision_static(collision::Constraints* constraints,
                          const Vector& movement, const Rectf& dest,
-                         GameObject& object)
+                         MovingObject& object)
 {
-  collision_tilemap(constraints, movement, dest);
+  collision_tilemap(constraints, movement, dest, object);
 
   // collision with other (static) objects
   for(MovingObjects::iterator i = moving_objects.begin();
index 595d857..f154766 100644 (file)
@@ -129,7 +129,8 @@ public:
   }
 
   void collision_tilemap(collision::Constraints* constraints,
-                         const Vector& movement, const Rectf& dest) const;
+                         const Vector& movement, const Rectf& dest,
+                         MovingObject &object) const;
 
   /**
    * Checks if the specified rectangle is free of (solid) tiles.
@@ -227,7 +228,7 @@ private:
    * (because of ABORT_MOVE in the collision response or no collisions)
    */
   void collision_static(collision::Constraints* constraints,
-                        const Vector& movement, const Rectf& dest, GameObject& object);
+                        const Vector& movement, const Rectf& dest, MovingObject& object);
 
   void collision_static_constrains(MovingObject& object);