using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
namespace MonoGame.Extended.Collisions
{
///
/// Represents a collision grid. This is used to break the game world into
/// chunks to detect collisions efficiently.
///
public class CollisionGrid
{
private readonly CollisionGridCell[] _data;
///
/// Creates a new collision grid of specified size.
///
///
/// Number of columns in the grid.
/// Number of rows in the grid.
/// The width of each individual cell.
/// The height of each individual cell.
public CollisionGrid(int[] data, int columns, int rows, int cellWidth, int cellHeight)
{
_data = new CollisionGridCell[data.Length];
for (var y = 0; y < rows; y++)
for (var x = 0; x < columns; x++)
{
var index = x + y*columns;
_data[index] = new CollisionGridCell(this, x, y, data[index]);
}
Columns = columns;
Rows = rows;
CellWidth = cellWidth;
CellHeight = cellHeight;
}
///
/// Gets the number of columns in this grid.
///
public int Columns { get; }
///
/// Gets the number of rows in this grid.
///
public int Rows { get; private set; }
///
/// Gets the width of each cell.
///
public int CellWidth { get; }
///
/// Gets the height of each cell.
///
public int CellHeight { get; }
public CollisionGridCell GetCellAtIndex(int column, int row)
{
var index = column + row*Columns;
if ((index < 0) || (index >= _data.Length))
return new CollisionGridCell(this, column, row, 0);
return _data[index];
}
public CollisionGridCell GetCellAtPosition(Vector3 position)
{
var column = (int) (position.X/CellWidth);
var row = (int) (position.Y/CellHeight);
return GetCellAtIndex(column, row);
}
public IEnumerable GetCellsOverlappingRectangle(RectangleF rectangle)
{
var sx = (int) (rectangle.Left/CellWidth);
var sy = (int) (rectangle.Top/CellHeight);
var ex = (int) (rectangle.Right/CellWidth + 1);
var ey = (int) (rectangle.Bottom/CellHeight + 1);
for (var y = sy; y < ey; y++)
for (var x = sx; x < ex; x++)
yield return GetCellAtIndex(x, y);
}
public IEnumerable GetCollidables(RectangleF overlappingRectangle)
{
return GetCellsOverlappingRectangle(overlappingRectangle)
.Where(cell => cell.Flag != CollisionGridCellFlag.Empty);
}
public Rectangle GetCellRectangle(int column, int row)
{
return new Rectangle(column*CellWidth, row*CellHeight, CellWidth, CellHeight);
}
}
}