Files
MonoGame.Extended/Source/MonoGame.Extended.Collisions/CollisionWorld.cs
T
Jon Seaman ce9fc2459b QuadTree Collision Library (#504)
* Created unit test project for collisions.

* Started on tests

* Created unit test project for collisions.

* Started on tests

* Update collision test

* CollisionInfo docs

* More docs for CollisionGrid and Cell

* Fix obsolete warning for RectangleF.Intersect

* Summary for CollisionGrid and CollisionGridCell

* QuadTree collision implemented

 - Ported from C++ from Game Physics Cookbook chapter 6, 2D Optimizations

* Small refactor for QuadTree naming

* First tests for QuadTree

* Fix test

* COde Cleanup

* Added DefaultMaxObjectsPerNode

* Add missed Query code

* Insert Tests and bugfix

* Fix bug with QuadTree.Shake

* Fix namespaces

* Query tests and fix

* Additional test for Query

* Initial QuadTreeCollision Component

* Basic collision demo working

* Spikey ball colliding with walls

* Improved the collision demo

* Update QuadTree

* Added comment for CollisionComponent

* Ignore test that needs fixed

* Rename QuadTree to Quadtree

* Fix penetration vector

* Update to 2.0 and xUnit
2018-05-30 20:26:34 +10:00

88 lines
2.8 KiB
C#

using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
namespace MonoGame.Extended.Collisions
{
public class CollisionWorld : IDisposable, IUpdate
{
private readonly List<CollisionActor> _actors;
private readonly Vector2 _gravity;
private CollisionGrid _grid;
public CollisionWorld(Vector2 gravity)
{
_gravity = gravity;
_actors = new List<CollisionActor>();
}
public void Dispose()
{
}
public void Update(GameTime gameTime)
{
var deltaTime = (float) gameTime.ElapsedGameTime.TotalSeconds;
foreach (var actor in _actors)
{
actor.Velocity += _gravity*deltaTime;
actor.Position += actor.Velocity*deltaTime;
if (_grid != null)
foreach (var collidable in _grid.GetCollidables(actor.BoundingBox))
{
var intersection = RectangleF.Intersection(collidable.BoundingBox, actor.BoundingBox);
if (intersection.IsEmpty)
continue;
var info = GetCollisionInfo(actor, collidable, intersection);
actor.OnCollision(info);
}
}
}
public CollisionActor CreateActor(IActorTarget target)
{
var actor = new CollisionActor(target);
_actors.Add(actor);
return actor;
}
public CollisionGrid CreateGrid(int[] data, int columns, int rows, int cellWidth, int cellHeight)
{
if (_grid != null)
throw new InvalidOperationException("Only one collision grid can be created per world");
_grid = new CollisionGrid(data, columns, rows, cellWidth, cellHeight);
return _grid;
}
private CollisionInfo GetCollisionInfo(ICollidable first, ICollidable second, RectangleF intersectingRectangle)
{
var info = new CollisionInfo
{
Other = second
};
if (intersectingRectangle.Width < intersectingRectangle.Height)
{
var d = first.BoundingBox.Center.X < second.BoundingBox.Center.X
? intersectingRectangle.Width
: -intersectingRectangle.Width;
info.PenetrationVector = new Vector2(d, 0);
}
else
{
var d = first.BoundingBox.Center.Y < second.BoundingBox.Center.Y
? intersectingRectangle.Height
: -intersectingRectangle.Height;
info.PenetrationVector = new Vector2(0, d);
}
return info;
}
}
}