+/*-------------------------------------------------------------------------
+ * Collision Detection
+ *-------------------------------------------------------------------------*/
+
+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, const Vector& addl_ground_movement = Vector(0,0))
+{
+ if(!collision::intersects(r1, r2))
+ return;
+
+ MovingObject *moving_object = dynamic_cast<MovingObject*> (object);
+ CollisionHit dummy;
+ if(other != NULL && !other->collides(*object, dummy))
+ return;
+ if(moving_object != NULL && !moving_object->collides(*other, dummy))
+ 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();
+
+ if(fabsf(movement.y) > fabsf(movement.x)) {
+ if(ileft < SHIFT_DELTA) {
+ constraints->right = std::min(constraints->right, r2.get_left());
+ return;
+ } else if(iright < SHIFT_DELTA) {
+ constraints->left = std::max(constraints->left, r2.get_right());
+ return;
+ }
+ } else {
+ // shiftout bottom/top
+ if(itop < SHIFT_DELTA) {
+ constraints->bottom = std::min(constraints->bottom, r2.get_top());
+ return;
+ } else if(ibottom < SHIFT_DELTA) {
+ constraints->top = std::max(constraints->top, r2.get_bottom());
+ return;
+ }
+ }
+
+ constraints->ground_movement += addl_ground_movement;
+ if(other != NULL) {
+ HitResponse response = other->collision(*object, dummy);
+ if(response == PASSTHROUGH)
+ return;
+
+ if(other->get_movement() != Vector(0, 0)) {
+ // TODO what todo when we collide with 2 moving objects?!?
+ constraints->ground_movement += other->get_movement();
+ }
+ }
+
+ float vert_penetration = std::min(itop, ibottom);
+ 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->hit.bottom = true;
+ } else {
+ constraints->top = std::max(constraints->top, r2.get_bottom());
+ constraints->hit.top = true;
+ }
+ } else {
+ if(ileft < iright) {
+ constraints->right = std::min(constraints->right, r2.get_left());
+ constraints->hit.right = true;
+ } else {
+ constraints->left = std::max(constraints->left, r2.get_right());
+ constraints->hit.left = true;
+ }
+ }
+}
+
+static const float DELTA = .001f;