Resolves issue 0000269: Moving tilemaps have improper physics
authorChristoph Sommer <mail@christoph-sommer.de>
Mon, 18 Feb 2008 20:07:06 +0000 (20:07 +0000)
committerChristoph Sommer <mail@christoph-sommer.de>
Mon, 18 Feb 2008 20:07:06 +0000 (20:07 +0000)
SVN-Revision: 5331

data/levels/test/tileplatforms.stl [new file with mode: 0644]
src/collision.cpp
src/collision.hpp
src/object/tilemap.cpp
src/object/tilemap.hpp
src/sector.cpp

diff --git a/data/levels/test/tileplatforms.stl b/data/levels/test/tileplatforms.stl
new file mode 100644 (file)
index 0000000..0f2d86b
--- /dev/null
@@ -0,0 +1,160 @@
+;;Uses 01 - Welcome to Antartica.stl as base\r
+(supertux-level\r
+  (version 2)\r
+  (name (_ "Demonstrates two tilemap platforms."))\r
+  (author "Mathnerd314")\r
+  (sector\r
+    (name "main")\r
+    (music "music/chipdisko.ogg")\r
+    (init-script "platform1.start_moving();platform2.start_moving();") ;needed for some reason (they don't move initially)\r
+    (ambient-light 1 1 1)\r
+    (spawnpoint\r
+      (name "main")\r
+      (x 100)\r
+      (y 100)\r
+    )\r
+    (background\r
+      (speed 0.5)\r
+      (image "images/background/arctis.jpg")\r
+    )\r
+    (tilemap\r
+      (z-pos -100)\r
+      (solid #f)\r
+      (speed 1)\r
+      (width 27)\r
+      (height 19)\r
+      (tiles\r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+      )\r
+    )\r
+    (tilemap\r
+      (z-pos 0)\r
+      (solid #t)\r
+      (speed 1)\r
+      (width 27)\r
+      (height 19)\r
+      (tiles\r
+0  0  0  0  0  0  0  0  0  0  0  0   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  126 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  \r
+7  8  8  8  8  8  8  8  8  8  8  8   8  8  8  8  8  8  8  8  9  0  0  0  0  0  0  \r
+13 14 14 14 14 14 14 14 14 14 14 14  14 14 14 14 14 14 14 14 15 0  0  0  0  0  0  \r
+10 11 11 11 11 11 11 11 11 11 11 11  11 11 11 11 11 11 11 11 12 0  0  0  0  0  0  \r
+      )\r
+    )\r
+    (tilemap\r
+      (z-pos 100)\r
+      (solid #f)\r
+      (speed 1)\r
+      (width 27)\r
+      (height 19)\r
+      (tiles\r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0   0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0   0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0   0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0   0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0   0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0   0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0   0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0   0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0   0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0   0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0   0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  127 0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0   0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0   0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0   0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0   0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0   0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0   0  0  0  0  0  0  0  0  0  0  0  0  \r
+0  0  0  0  0  0  0  0  0  0  0  0  0  0  0   0  0  0  0  0  0  0  0  0  0  0  0  \r
+      )\r
+    )\r
+    (tilemap\r
+      (name "platform1")\r
+      (z-pos 1)\r
+      (solid #t)\r
+      (speed 1)\r
+      (speed-y 1)\r
+      (path\r
+        (mode "circular")\r
+        (node\r
+          (x 224)\r
+          (y 192)\r
+          (time 5)\r
+        )\r
+        (node\r
+          (x 224)\r
+          (y 472)\r
+          (time 5)\r
+        )\r
+      )\r
+      (width 5)\r
+      (height 3)\r
+      (tiles\r
+        7  8  8  8  9 \r
+        13 14 14 14 15\r
+        16 17 17 17 18\r
+      )\r
+    )\r
+    (tilemap\r
+      (name "platform2")\r
+      (z-pos 2)\r
+      (solid #t)\r
+      (speed 1)\r
+      (speed-y 1)\r
+      (path\r
+        (mode "circular")\r
+        (node\r
+          (x 86)\r
+          (y 450)\r
+          (time 1)\r
+        )\r
+        (node\r
+          (x 200)\r
+          (y 450)\r
+          (time 1)\r
+        )\r
+      )\r
+      (width 5)\r
+      (height 1)\r
+      (tiles\r
+        27 28 28 28 29\r
+      )\r
+    )\r
+    (camera\r
+      (mode "normal")\r
+    )\r
+  )\r
+)\r
index f96fdea..6ff2295 100644 (file)
@@ -61,7 +61,7 @@ namespace {
 }
 
 bool rectangle_aatriangle(Constraints* constraints, const Rect& rect,
-    const AATriangle& triangle)
+    const AATriangle& triangle, const Vector& addl_ground_movement)
 {
   if(!intersects(rect, (const Rect&) triangle))
     return false;
@@ -146,6 +146,7 @@ bool rectangle_aatriangle(Constraints* constraints, const Rect& rect,
     if(outvec.y < 0) {
       constraints->bottom = rect.get_bottom() + outvec.y;
       constraints->hit.bottom = true;
+      constraints->ground_movement += addl_ground_movement;
     } else {
       constraints->top = rect.get_top() + outvec.y;
       constraints->hit.top = true;
@@ -157,7 +158,7 @@ bool rectangle_aatriangle(Constraints* constraints, const Rect& rect,
 }
 
 void set_rectangle_rectangle_constraints(Constraints* constraints,
-        const Rect& r1, const Rect& r2)
+        const Rect& r1, const Rect& r2, const Vector& addl_ground_movement)
 {
   float itop = r1.get_bottom() - r2.get_top();
   float ibottom = r2.get_bottom() - r1.get_top();
@@ -170,6 +171,7 @@ void set_rectangle_rectangle_constraints(Constraints* constraints,
     if(itop < ibottom) {
       constraints->bottom = std::min(constraints->bottom, r2.get_top());
       constraints->hit.bottom = true;
+      constraints->ground_movement += addl_ground_movement;
     } else {
       constraints->top = std::max(constraints->top, r2.get_bottom());
       constraints->hit.top = true;
index ba6b6f8..a31878c 100644 (file)
@@ -63,10 +63,10 @@ bool intersects(const Rect& r1, const Rect& r2);
  * Returns true in case of a collision and fills in the hit structure then.
  */
 bool rectangle_aatriangle(Constraints* constraints, const Rect& rect,
-                                   const AATriangle& triangle);
+                                   const AATriangle& triangle, const Vector& addl_ground_movement = Vector(0,0));
 
 void set_rectangle_rectangle_constraints(Constraints* constraints,
-        const Rect& r1, const Rect& r2);
+        const Rect& r1, const Rect& r2, const Vector& addl_ground_movement = Vector(0,0));
 
 }
 
index 1c4e490..d24caca 100644 (file)
@@ -44,7 +44,7 @@
 
 TileMap::TileMap(const TileSet *new_tileset)
   : tileset(new_tileset), solid(false), speed_x(1), speed_y(1), width(0),
-    height(0), z_pos(0), x_offset(0), y_offset(0), drawing_effect(NO_EFFECT),
+    height(0), z_pos(0), x_offset(0), y_offset(0), movement(Vector(0,0)), drawing_effect(NO_EFFECT),
     alpha(1.0), current_alpha(1.0), remaining_fade_time(0),
     draw_target(DrawingContext::NORMAL)
 {
@@ -52,7 +52,7 @@ TileMap::TileMap(const TileSet *new_tileset)
 
 TileMap::TileMap(const lisp::Lisp& reader)
   : solid(false), speed_x(1), speed_y(1), width(-1),
-    height(-1), z_pos(0), x_offset(0), y_offset(0), drawing_effect(NO_EFFECT),
+    height(-1), z_pos(0), x_offset(0), y_offset(0), movement(Vector(0,0)), drawing_effect(NO_EFFECT),
     alpha(1.0), current_alpha(1.0), remaining_fade_time(0),
     draw_target(DrawingContext::NORMAL)
 {
@@ -110,7 +110,7 @@ TileMap::TileMap(const lisp::Lisp& reader)
 TileMap::TileMap(const TileSet *new_tileset, std::string name, int z_pos,
                  bool solid, size_t width, size_t height)
   : tileset(new_tileset), solid(solid), speed_x(1), speed_y(1), width(0),
-    height(0), z_pos(z_pos), x_offset(0), y_offset(0),
+    height(0), z_pos(z_pos), x_offset(0), y_offset(0), movement(Vector(0,0)),
     drawing_effect(NO_EFFECT), alpha(1.0), current_alpha(1.0),
     remaining_fade_time(0), draw_target(DrawingContext::NORMAL)
 {
@@ -157,9 +157,11 @@ TileMap::update(float elapsed_time)
     if ((alpha > 0.75) && (current_alpha > 0.75)) set_solid(true);
   }
 
+  movement = Vector(0,0);
   // if we have a path to follow, follow it
   if (walker.get()) {
     Vector v = walker->advance(elapsed_time);
+    movement = Vector(v.x-get_x_offset(), std::max(0.0f,v.y-get_y_offset()));
     set_x_offset(v.x);
     set_y_offset(v.y);
   }
index d6ee518..d67049d 100644 (file)
@@ -90,6 +90,11 @@ public:
   float get_y_offset() const
   { return y_offset; }
 
+  const Vector& get_movement() const
+  {
+    return movement;
+  }
+
   void set_x_offset(float x_offset)
   { this->x_offset = x_offset; }
 
@@ -162,6 +167,7 @@ private:
   int z_pos;
   float x_offset;
   float y_offset;
+  Vector movement; /**< The movement that happened last frame */
 
   DrawingEffect drawing_effect;
   float alpha; /**< requested tilemap opacity */
index 253212b..686efc9 100644 (file)
@@ -887,7 +887,7 @@ static const float SHIFT_DELTA = 7.0f;
 /** r1 is supposed to be moving, r2 a solid object */
 void check_collisions(collision::Constraints* constraints,
                       const Vector& movement, const Rect& r1, const Rect& r2,
-                      GameObject* object = NULL, MovingObject* other = NULL)
+                      GameObject* object = NULL, MovingObject* other = NULL, const Vector& addl_ground_movement = Vector(0,0))
 {
   if(!collision::intersects(r1, r2))
     return;
@@ -924,6 +924,7 @@ void check_collisions(collision::Constraints* constraints,
     }
   }
 
+  constraints->ground_movement += addl_ground_movement;
   if(other != NULL) {
     HitResponse response = other->collision(*object, dummy);
     if(response == PASSTHROUGH)
@@ -931,7 +932,7 @@ void check_collisions(collision::Constraints* constraints,
 
     if(other->get_movement() != Vector(0, 0)) {
       // TODO what todo when we collide with 2 moving objects?!?
-      constraints->ground_movement = other->get_movement();
+      constraints->ground_movement += other->get_movement();
     }
   }
 
@@ -998,10 +999,10 @@ Sector::collision_tilemap(collision::Constraints* constraints,
          Vector p2((x+1)*32 + solids->get_x_offset(), (y+1)*32 + solids->get_y_offset());
          triangle = AATriangle(p1, p2, tile->getData());
 
-         collision::rectangle_aatriangle(constraints, dest, triangle);
+         collision::rectangle_aatriangle(constraints, dest, triangle, solids->get_movement());
        } else { // normal rectangular tile
          Rect rect(x*32 + solids->get_x_offset(), y*32 + solids->get_y_offset(), (x+1)*32 + solids->get_x_offset(), (y+1)*32 + solids->get_y_offset());
-         check_collisions(constraints, movement, dest, rect);
+         check_collisions(constraints, movement, dest, rect, NULL, NULL, solids->get_movement());
        }
       }
     }