set_rectangle_rectangle_constraints(constraints, rect, area);
   } else {
     if(outvec.x < 0) {
-      constraints->constrain_right(rect.get_right() + outvec.x);
+      constraints->constrain_right(rect.get_right() + outvec.x, addl_ground_movement.x);
     } else {
-      constraints->constrain_left(rect.get_left() + outvec.x);
+      constraints->constrain_left(rect.get_left() + outvec.x, addl_ground_movement.x);
     }
 
     if(outvec.y < 0) {
-      constraints->constrain_bottom(rect.get_bottom() + outvec.y);
+      constraints->constrain_bottom(rect.get_bottom() + outvec.y, addl_ground_movement.y);
       constraints->hit.bottom = true;
       constraints->ground_movement += addl_ground_movement;
     } else {
-      constraints->constrain_top(rect.get_top() + outvec.y);
+      constraints->constrain_top(rect.get_top() + outvec.y, addl_ground_movement.y);
       constraints->hit.top = true;
     }
     constraints->hit.slope_normal = normal;
   float horiz_penetration = std::min(ileft, iright);
   if(vert_penetration < horiz_penetration) {
     if(itop < ibottom) {
-      constraints->constrain_bottom(r2.get_top());
+      constraints->constrain_bottom(r2.get_top(), addl_ground_movement.y);
       constraints->hit.bottom = true;
       constraints->ground_movement += addl_ground_movement;
     } else {
-      constraints->constrain_top(r2.get_bottom());
+      constraints->constrain_top(r2.get_bottom(), addl_ground_movement.y);
       constraints->hit.top = true;
     }
   } else {
     if(ileft < iright) {
-      constraints->constrain_right(r2.get_left());
+      constraints->constrain_right(r2.get_left(), addl_ground_movement.x);
       constraints->hit.right = true;
     } else {
-      constraints->constrain_left(r2.get_right());
+      constraints->constrain_left(r2.get_right(), addl_ground_movement.x);
       constraints->hit.left = true;
     }
   }
 
 {
 public:
   Constraints() :
-    left(),
-    right(),
-    top(),
-    bottom(),
+    position_left(),
+    position_right(),
+    position_top(),
+    position_bottom(),
+    speed_left(),
+    speed_right(),
+    speed_top(),
+    speed_bottom(),
     ground_movement(),
     hit()
   {
     float infinity = (std::numeric_limits<float>::has_infinity ? 
                       std::numeric_limits<float>::infinity() : 
                       std::numeric_limits<float>::max());
-    left = -infinity;
-    right = infinity;
-    top = -infinity;
-    bottom = infinity;
+    position_left = -infinity;
+    position_right = infinity;
+    position_top = -infinity;
+    position_bottom = infinity;
+
+    speed_left = -infinity;
+    speed_right = infinity;
+    speed_top = -infinity;
+    speed_bottom = infinity;
   }
 
   bool has_constraints() const 
                       std::numeric_limits<float>::infinity() : 
                       std::numeric_limits<float>::max());
     return
-      left   > -infinity || 
-      right  <  infinity || 
-      top    > -infinity || 
-      bottom <  infinity;
+      position_left   > -infinity || 
+      position_right  <  infinity || 
+      position_top    > -infinity || 
+      position_bottom <  infinity;
   }
 
 public:
-  float left;
-  float right;
-  float top;
-  float bottom;
 
-  void constrain_left  (float left2  ) { left   = std::max(left  , left2  ); }
-  void constrain_right (float right2 ) { right  = std::min(right , right2 ); }
-  void constrain_top   (float top2   ) { top    = std::max(top   , top2   ); }
-  void constrain_bottom(float bottom2) { bottom = std::min(bottom, bottom2); }
+  void constrain_left (float position, float velocity)
+  {
+    position_left = std::max (position_left, position);
+    speed_left = std::max (speed_left, velocity);
+  }
+
+  void constrain_right (float position, float velocity)
+  {
+    position_right = std::min (position_right, position);
+    speed_right = std::min (speed_right, velocity);
+  }
+
+  void constrain_top (float position, float velocity)
+  {
+    position_top = std::max (position_top, position);
+    speed_top = std::max (speed_top, velocity);
+  }
+
+  void constrain_bottom (float position, float velocity)
+  {
+    position_bottom = std::min (position_bottom, position);
+    speed_bottom = std::min (speed_bottom, velocity);
+  }
+
+  float get_position_left   (void) const { return position_left;   }
+  float get_position_right  (void) const { return position_right;  }
+  float get_position_top    (void) const { return position_top;    }
+  float get_position_bottom (void) const { return position_bottom; }
+
+  float get_height (void) const { return (position_bottom - position_top); }
+  float get_width  (void) const { return (position_right - position_left); }
+
+  float get_x_midpoint (void) const { return (.5f * (position_left + position_right)); }
 
   Vector ground_movement;
   CollisionHit hit;
+
+private:
+  float position_left;
+  float position_right;
+  float position_top;
+  float position_bottom;
+
+  float speed_left;
+  float speed_right;
+  float speed_top;
+  float speed_bottom;
 };
 
 /** checks if 2 rectangle intersect each other */
 
 
 /** r1 is supposed to be moving, r2 a solid object */
 void check_collisions(collision::Constraints* constraints,
-                      const Vector& movement, const Rectf& r1, const Rectf& r2,
-                      GameObject* object = NULL, MovingObject* other = NULL, const Vector& addl_ground_movement = Vector(0,0))
+                      const Vector& obj_movement, const Rectf& obj_rect, const Rectf& other_rect,
+                      GameObject* object = NULL, MovingObject* other = NULL, const Vector& other_movement = Vector(0,0))
 {
-  if(!collision::intersects(r1, r2))
+  if(!collision::intersects(obj_rect, other_rect))
     return;
 
   MovingObject *moving_object = dynamic_cast<MovingObject*> (object);
     return;
 
   // calculate intersection
-  float itop    = r1.get_bottom() - r2.get_top();
-  float ibottom = r2.get_bottom() - r1.get_top();
-  float ileft   = r1.get_right() - r2.get_left();
-  float iright  = r2.get_right() - r1.get_left();
+  float itop    = obj_rect.get_bottom() - other_rect.get_top();
+  float ibottom = other_rect.get_bottom() - obj_rect.get_top();
+  float ileft   = obj_rect.get_right() - other_rect.get_left();
+  float iright  = other_rect.get_right() - obj_rect.get_left();
 
-  if(fabsf(movement.y) > fabsf(movement.x)) {
+  if(fabsf(obj_movement.y) > fabsf(obj_movement.x)) {
     if(ileft < SHIFT_DELTA) {
-      constraints->constrain_right(r2.get_left());
+      constraints->constrain_right(other_rect.get_left(), other_movement.x);
       return;
     } else if(iright < SHIFT_DELTA) {
-      constraints->constrain_left(r2.get_right());
+      constraints->constrain_left(other_rect.get_right(), other_movement.x);
       return;
     }
   } else {
     // shiftout bottom/top
     if(itop < SHIFT_DELTA) {
-      constraints->constrain_bottom(r2.get_top());
+      constraints->constrain_bottom(other_rect.get_top(), other_movement.y);
       return;
     } else if(ibottom < SHIFT_DELTA) {
-      constraints->constrain_top(r2.get_bottom());
+      constraints->constrain_top(other_rect.get_bottom(), other_movement.y);
       return;
     }
   }
 
-  constraints->ground_movement += addl_ground_movement;
+  constraints->ground_movement += other_movement;
   if(other != NULL) {
     HitResponse response = other->collision(*object, dummy);
     if(response == ABORT_MOVE)
   float horiz_penetration = std::min(ileft, iright);
   if(vert_penetration < horiz_penetration) {
     if(itop < ibottom) {
-      constraints->constrain_bottom(r2.get_top());
+      constraints->constrain_bottom(other_rect.get_top(), other_movement.y);
       constraints->hit.bottom = true;
     } else {
-      constraints->constrain_top(r2.get_bottom());
+      constraints->constrain_top(other_rect.get_bottom(), other_movement.y);
       constraints->hit.top = true;
     }
   } else {
     if(ileft < iright) {
-      constraints->constrain_right(r2.get_left());
+      constraints->constrain_right(other_rect.get_left(), other_movement.x);
       constraints->hit.right = true;
     } else {
-      constraints->constrain_left(r2.get_right());
+      constraints->constrain_left(other_rect.get_right(), other_movement.x);
       constraints->hit.left = true;
     }
   }
       break;
 
     // apply calculated horizontal constraints
-    if(constraints.bottom < infinity) {
-      float height = constraints.bottom - constraints.top;
+    if(constraints.get_position_bottom() < infinity) {
+      float height = constraints.get_height ();
       if(height < oheight) {
         // we're crushed, but ignore this for now, we'll get this again
         // later if we're really crushed or things will solve itself when
         // looking at the vertical constraints
       }
-      dest.p2.y = constraints.bottom - DELTA;
+      dest.p2.y = constraints.get_position_bottom() - DELTA;
       dest.p1.y = dest.p2.y - oheight;
-    } else if(constraints.top > -infinity) {
-      dest.p1.y = constraints.top + DELTA;
+    } else if(constraints.get_position_top() > -infinity) {
+      dest.p1.y = constraints.get_position_top() + DELTA;
       dest.p2.y = dest.p1.y + oheight;
     }
   }
       break;
 
     // apply calculated vertical constraints
-    float width = constraints.right - constraints.left;
+    float width = constraints.get_width ();
     if(width < infinity) {
       if(width + SHIFT_DELTA < owidth) {
 #if 0
         printf("Object %p crushed horizontally... L:%f R:%f\n", &object,
-               constraints.left, constraints.right);
+               constraints.get_position_left(), constraints.get_position_right());
 #endif
         CollisionHit h;
         h.left = true;
         h.crush = true;
         object.collision_solid(h);
       } else {
-        float xmid = (constraints.left + constraints.right) / 2;
+        float xmid = constraints.get_x_midpoint ();
         dest.p1.x = xmid - owidth/2;
         dest.p2.x = xmid + owidth/2;
       }
-    } else if(constraints.right < infinity) {
-      dest.p2.x = constraints.right - DELTA;
+    } else if(constraints.get_position_right() < infinity) {
+      dest.p2.x = constraints.get_position_right() - DELTA;
       dest.p1.x = dest.p2.x - owidth;
-    } else if(constraints.left > -infinity) {
-      dest.p1.x = constraints.left + DELTA;
+    } else if(constraints.get_position_left() > -infinity) {
+      dest.p1.x = constraints.get_position_left() + DELTA;
       dest.p2.x = dest.p1.x + owidth;
     }
   }
   // an extra pass to make sure we're not crushed horizontally
   constraints = Constraints();
   collision_static(&constraints, movement, dest, object);
-  if(constraints.bottom < infinity) {
-    float height = constraints.bottom - constraints.top;
+  if(constraints.get_position_bottom() < infinity) {
+    float height = constraints.get_height ();
     if(height + SHIFT_DELTA < oheight) {
 #if 0
       printf("Object %p crushed vertically...\n", &object);
   return gravity;
 }
 
+/* vim: set sw=2 sts=2 et : */
 /* EOF */