public void ApplyPhysics(PhysicalProperties entityProps, IPhysicsObject entity, GameTime gameTime) { var delta = (float)gameTime.ElapsedGameTime.TotalSeconds; var lastPos = entityProps.Position; var neighbours = new IPhysicsObject[0]; var overlappingObjs = new List <IPhysicsObject>(); // [ Y ] entityProps.Position.Y += (entityProps.Velocity.Y * delta); // get new neighbours since objects have probably moved neighbours = chunkMap.GetNearbyCollidables(entity); // overlaps if (entity.IsOverlappingEnabled) { var overlaps = neighbours.Where(n => n.IsOverlappingEnabled && entity.OverlapBox.IntersectsWith(n.OverlapBox)); foreach (var overlap in overlaps) { overlap.OnOverlapping(entity); entity.OnOverlapping(overlap); if (!overlappingObjs.Contains(overlap)) { overlappingObjs.Add(overlap); } } } // collision if (entity.IsCollisionEnabled) { var collisions = neighbours.Where(n => n.IsCollisionEnabled && entity.CollisionBox.IntersectsWith(n.CollisionBox)); var hasCollided = false; foreach (var collision in collisions) { if (hasCollided) { continue; } hasCollided = true; var up = entityProps.Velocity.Y < 0; entityProps.Velocity.Y = 0; if (up) { entityProps.Position.Y = collision.CollisionBox.Bottom + 1; } else { entityProps.Position.Y = collision.CollisionBox.Top - entity.CollisionBox.Height; } collision.OnCollision(entity); entity.OnCollision(collision); } } // [ X ] entityProps.Position.X = entityProps.Position.X + (entityProps.Velocity.X * delta); // get new neighbours since objects have probably moved neighbours = chunkMap.GetNearbyCollidables(entity); if (entity.IsOverlappingEnabled) { // overlaps var overlaps = neighbours.Where(n => n.IsOverlappingEnabled && entity.OverlapBox.IntersectsWith(n.OverlapBox)); foreach (var overlap in overlaps) { overlap.OnOverlapping(entity); entity.OnOverlapping(overlap); if (!overlappingObjs.Contains(overlap)) { overlappingObjs.Add(overlap); } } } if (entity.IsCollisionEnabled) { // collision var collisions = neighbours.Where(n => n.IsCollisionEnabled && entity.CollisionBox.IntersectsWith(n.CollisionBox)); var hasCollided = false; foreach (var collision in collisions) { if (hasCollided) { continue; } hasCollided = true; entityProps.Velocity.X = 0; entityProps.Position.X = lastPos.X; collision.OnCollision(entity); entity.OnCollision(collision); } } // track overlappers entityProps.OverlappingObjects = overlappingObjs; // get new neighbours since objects have probably moved neighbours = chunkMap.GetNearbyCollidables(entity); switch (physSettings.PhysicsType) { case PhysicsType.Platformer: handlePlatformerAdditionalPhysics(entityProps, entity, neighbours, gameTime); break; case PhysicsType.Topdown: handleTopDownAdditionalPhysics(entityProps, entity, neighbours, gameTime); break; } // [ Chunk map update ] chunkMap.UpdateEntity(entity); }