Bug 456: Avoid hurting Tux in a ravine.
authorFlorian Forster <supertux@octo.it>
Sat, 30 Jan 2010 09:23:14 +0000 (09:23 +0000)
committerFlorian Forster <supertux@octo.it>
Sat, 30 Jan 2010 09:23:14 +0000 (09:23 +0000)
- Fix blooper where slope constraints overwrote previously calculated
  constraints.
- Make static collision detection symmetrical left-right.

There are still a lot of things wrong with static collision detection,
which I hope to fix later.

SVN-Revision: 6284

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

index 6729d05..f3dc041 100644 (file)
@@ -121,21 +121,19 @@ bool rectangle_aatriangle(Constraints* constraints, const Rectf& rect,
   if(p1.x < area.p1.x - RDELTA || p1.x > area.p2.x + RDELTA
      || p1.y < area.p1.y - RDELTA || p1.y > area.p2.y + RDELTA) {
     set_rectangle_rectangle_constraints(constraints, rect, area);
-    constraints->hit.left = false;
-    constraints->hit.right = false;
   } else {
     if(outvec.x < 0) {
-      constraints->right = rect.get_right() + outvec.x;
+      constraints->min_right(rect.get_right() + outvec.x);
     } else {
-      constraints->left = rect.get_left() + outvec.x;
+      constraints->max_left(rect.get_left() + outvec.x);
     }
 
     if(outvec.y < 0) {
-      constraints->bottom = rect.get_bottom() + outvec.y;
+      constraints->min_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->max_top(rect.get_top() + outvec.y);
       constraints->hit.top = true;
     }
     constraints->hit.slope_normal = normal;
@@ -156,19 +154,19 @@ void set_rectangle_rectangle_constraints(Constraints* constraints,
   float horiz_penetration = std::min(ileft, iright);
   if(vert_penetration < horiz_penetration) {
     if(itop < ibottom) {
-      constraints->bottom = std::min(constraints->bottom, r2.get_top());
+      constraints->min_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->max_top(r2.get_bottom());
       constraints->hit.top = true;
     }
   } else {
     if(ileft < iright) {
-      constraints->right = std::min(constraints->right, r2.get_left());
+      constraints->min_right(r2.get_left());
       constraints->hit.right = true;
     } else {
-      constraints->left = std::max(constraints->left, r2.get_right());
+      constraints->max_left(r2.get_right());
       constraints->hit.left = true;
     }
   }
index a500a2b..14d15b0 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "supertux/collision_hit.hpp"
 #include <limits>
+#include <algorithm> /* min/max */
 
 class Vector;
 class Rectf;
@@ -63,6 +64,12 @@ public:
   float right;
   float top;
   float bottom;
+
+  void max_left  (float left2  ) { left   = std::max(left  , left2  ); }
+  void min_right (float right2 ) { right  = std::min(right , right2 ); }
+  void max_top   (float top2   ) { top    = std::max(top   , top2   ); }
+  void min_bottom(float bottom2) { bottom = std::min(bottom, bottom2); }
+
   Vector ground_movement;
   CollisionHit hit;
 };
index d337fc8..2cbbeb9 100644 (file)
@@ -902,19 +902,19 @@ void check_collisions(collision::Constraints* constraints,
 
   if(fabsf(movement.y) > fabsf(movement.x)) {
     if(ileft < SHIFT_DELTA) {
-      constraints->right = std::min(constraints->right, r2.get_left());
+      constraints->min_right(r2.get_left());
       return;
     } else if(iright < SHIFT_DELTA) {
-      constraints->left = std::max(constraints->left, r2.get_right());
+      constraints->max_left(r2.get_right());
       return;
     }
   } else {
     // shiftout bottom/top
     if(itop < SHIFT_DELTA) {
-      constraints->bottom = std::min(constraints->bottom, r2.get_top());
+      constraints->min_bottom(r2.get_top());
       return;
     } else if(ibottom < SHIFT_DELTA) {
-      constraints->top = std::max(constraints->top, r2.get_bottom());
+      constraints->max_top(r2.get_bottom());
       return;
     }
   }
@@ -935,18 +935,18 @@ void check_collisions(collision::Constraints* constraints,
   float horiz_penetration = std::min(ileft, iright);
   if(vert_penetration < horiz_penetration) {
     if(itop < ibottom) {
-      constraints->bottom = std::min(constraints->bottom, r2.get_top());
+      constraints->min_bottom(r2.get_top());
       constraints->hit.bottom = true;
     } else {
-      constraints->top = std::max(constraints->top, r2.get_bottom());
+      constraints->max_top(r2.get_bottom());
       constraints->hit.top = true;
     }
   } else {
     if(ileft < iright) {
-      constraints->right = std::min(constraints->right, r2.get_left());
+      constraints->min_right(r2.get_left());
       constraints->hit.right = true;
     } else {
-      constraints->left = std::max(constraints->left, r2.get_right());
+      constraints->max_left(r2.get_right());
       constraints->hit.left = true;
     }
   }
@@ -1184,8 +1184,8 @@ Sector::collision_static_constrains(MovingObject& object)
       break;
 
     // apply calculated vertical constraints
-    if(constraints.right < infinity) {
-      float width = constraints.right - constraints.left;
+    float width = constraints.right - constraints.left;
+    if(width < infinity) {
       if(width + SHIFT_DELTA < owidth) {
 #if 0
         printf("Object %p crushed horizontally... L:%f R:%f\n", &object,
@@ -1197,9 +1197,13 @@ Sector::collision_static_constrains(MovingObject& object)
         h.crush = true;
         object.collision_solid(h);
       } else {
-        dest.p2.x = constraints.right - DELTA;
-        dest.p1.x = dest.p2.x - owidth;
+        float xmid = (constraints.left + constraints.right) / 2;
+        dest.p1.x = xmid - owidth/2;
+        dest.p2.x = xmid + owidth/2;
       }
+    } else if(constraints.right < infinity) {
+      dest.p2.x = constraints.right - DELTA;
+      dest.p1.x = dest.p2.x - owidth;
     } else if(constraints.left > -infinity) {
       dest.p1.x = constraints.left + DELTA;
       dest.p2.x = dest.p1.x + owidth;