private const float _topEdge = 0; // Y coordinate of the top edge of the playable area public PhysicsManager(GraphicsDevice g, General.World world) { World = world; StaticObjects = new List <PhysObject>(); DynamicObjects = new List <PhysObject>(); AllPhysObjects = new List <PhysObject>(); DeletionList = new List <PhysObject>(); CollisionHandler = new CollisionHandler(); Gravity = new Vector2(0.0f, 500f); IgnoreCollision = false; MaximumHorizontalSpeed = 400.0f; MaximumVerticalSpeed = 600.0f; // Create the game world physics objects CreateEnvironment(g); CollisionHandler.World = World; }
// Detect collisions (uses AABB detection) private void CollisionDetection() { for (int i = DynamicObjects.Count - 1; i >= 0; i--) { RigidBody bodyA = DynamicObjects[i].RigidBody; AABB physObject_A_AABB = bodyA.CollidableObject.CalculateAABB(bodyA); for (int j = AllPhysObjects.Count - 1; j >= 0; j--) { if (bodyA != AllPhysObjects[j].RigidBody) { RigidBody bodyB = AllPhysObjects[j].RigidBody; AABB physObject_B_AABB = bodyB.CollidableObject.CalculateAABB(bodyB); // Check if the two objects are colliding if (CheckIntersection_AABB(physObject_A_AABB, physObject_B_AABB)) { CollisionData collision = new CollisionData(); collision.BodyA = DynamicObjects[i]; collision.BodyB = AllPhysObjects[j]; if (collision.BodyA is Character && collision.BodyB is Character) { collision.IgnoreCollision = IgnoreCollision; } // Vector between the centre of each body Vector2 separator = bodyB.Position - bodyA.Position; // The distance each axis on body A has penetrated into body B float xSeparator = (bodyA.Width / 2 + bodyB.Width / 2) - Math.Abs(separator.X); float ySeparator = (bodyA.Height / 2 + bodyB.Height / 2) - Math.Abs(separator.Y); if (!bodyB.CollidableObject.IsCircle) { if (xSeparator > ySeparator) { // Body A has collided with body B from above if (bodyA.Position.Y < bodyB.Position.Y) { collision.ContactNormal = new Vector2(0, -1); collision.ContactPoint = bodyA.Position - new Vector2(0, -0.2f); } // Body A has collided with body B from below else { collision.ContactNormal = new Vector2(0, 1); collision.ContactPoint = bodyA.Position - new Vector2(0, 0.2f); } collision.BodyA.TimeSinceLastCollision = 0; collision.BodyA.TimeSinceLastCollisionWithFloor = 0; // If it is a dynamic object, set the counter since last collision to 0 if (bodyB.IsDynamic && !collision.BodyA.IsTarget) { collision.BodyB.TimeSinceLastCollision = 0; // If it collided with the floor, set the counter since last collision with floor to 0 collision.BodyB.TimeSinceLastCollisionWithFloor = 0; } } else { // Body A has collided with body B from the left if (bodyA.Position.X < bodyB.Position.X) { collision.ContactNormal = new Vector2(-1, 0); collision.ContactPoint = bodyA.Position - new Vector2(-0.2f, 0); } // Body B has collided with body B from the right else { collision.ContactNormal = new Vector2(1, 0); collision.ContactPoint = bodyA.Position - new Vector2(0.2f, 0); } } } else { // Normal must be the distance between the two objects, normalised collision.ContactNormal = Vector2.Normalize(separator); collision.ContactPoint = bodyA.Position + collision.ContactNormal; } CollisionHandler.AddCollision(collision); } } } } CollisionHandler.ResolveAllCollisions(); }