+
+ // up to 4 tries
+ for(int t = 0; t < 4; ++t) {
+ CollisionHit hit;
+ hit.time = -1;
+ MovingObject* collided_with = NULL;
+
+ // collision with tilemap
+ collision_tilemap(moving_object, hit);
+
+ // collision with other objects
+ Rect dest1 = moving_object->get_bbox();
+ dest1.move(moving_object->get_movement());
+ CollisionHit temphit;
+
+ for(MovingObjects::iterator i2 = moving_objects.begin();
+ i2 != moving_objects.end(); ++i2) {
+ MovingObject* moving_object_2 = *i2;
+ if(moving_object_2->get_group() != COLGROUP_STATIC
+ || !moving_object_2->is_valid())
+ continue;
+
+ Rect dest2 = moving_object_2->get_bbox();
+ dest2.move(moving_object_2->get_movement());
+ Vector movement
+ = moving_object->get_movement() - moving_object_2->get_movement();
+ if(Collision::rectangle_rectangle(temphit, dest1, movement, dest2)
+ && temphit.time > hit.time) {
+ hit = temphit;
+ collided_with = moving_object_2;
+ }
+ }
+
+ if(hit.time < 0)
+ break;
+
+ // call collision callbacks
+ HitResponse response;
+ if(collided_with != 0) {
+ response = moving_object->collision(*collided_with, hit);
+ hit.normal *= -1;
+ collided_with->collision(*moving_object, hit);
+ } else {
+ response = moving_object->collision(*solids, hit);
+ hit.normal *= -1;
+ }
+
+ if(response == CONTINUE) {
+ moving_object->movement += -hit.normal * (hit.depth + DELTA);
+ } else if(response == ABORT_MOVE) {
+ moving_object->movement = Vector(0, 0);
+ break;
+ } else { // force move
+ break;
+ }
+ }
+ }
+
+ // part2: COLGROUP_MOVING vs tile attributes
+ for(MovingObjects::iterator i = moving_objects.begin();
+ i != moving_objects.end(); ++i) {
+ MovingObject* moving_object = *i;
+ if((moving_object->get_group() != COLGROUP_MOVING
+ && moving_object->get_group() != COLGROUP_MOVING_ONLY_STATIC)
+ || !moving_object->is_valid())