mirror of
https://github.com/AlexMacocian/MonoGame.Extended.git
synced 2026-07-21 01:39:32 +00:00
working on collisions
This commit is contained in:
@@ -3,14 +3,14 @@ using MonoGame.Extended.Shapes;
|
||||
|
||||
namespace MonoGame.Extended.Collisions
|
||||
{
|
||||
public class CollisionBody : ICollidable
|
||||
public class CollisionBody : IDynamicCollidable
|
||||
{
|
||||
public CollisionBody(ICollidable target)
|
||||
public CollisionBody(IDynamicCollidable target)
|
||||
{
|
||||
_target = target;
|
||||
}
|
||||
|
||||
private readonly ICollidable _target;
|
||||
private readonly IDynamicCollidable _target;
|
||||
|
||||
public Vector2 Velocity
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Xna.Framework;
|
||||
using MonoGame.Extended.Shapes;
|
||||
|
||||
@@ -6,9 +7,18 @@ namespace MonoGame.Extended.Collisions
|
||||
{
|
||||
public class CollisionGrid
|
||||
{
|
||||
public CollisionGrid(byte[] data, int columns, int rows, int cellWidth, int cellHeight)
|
||||
public CollisionGrid(int[] data, int columns, int rows, int cellWidth, int cellHeight)
|
||||
{
|
||||
_data = data;
|
||||
_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(x, y, data[index]);
|
||||
}
|
||||
}
|
||||
|
||||
Columns = columns;
|
||||
Rows = rows;
|
||||
@@ -21,18 +31,40 @@ namespace MonoGame.Extended.Collisions
|
||||
public int CellWidth { get; private set; }
|
||||
public int CellHeight { get; private set; }
|
||||
|
||||
private readonly byte[] _data;
|
||||
private readonly CollisionGridCell[] _data;
|
||||
|
||||
public byte GetDataAt(int column, int row)
|
||||
public CollisionGridCell GetCellAtIndex(int column, int row)
|
||||
{
|
||||
var index = column + row * Columns;
|
||||
|
||||
if (index < 0 || index >= _data.Length)
|
||||
return 0;
|
||||
return new CollisionGridCell(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<CollisionGridCell> 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 Rectangle GetCellRectangle(int column, int row)
|
||||
{
|
||||
return new Rectangle(column * CellWidth, row * CellHeight, CellWidth, CellHeight);
|
||||
@@ -40,43 +72,27 @@ namespace MonoGame.Extended.Collisions
|
||||
|
||||
public void CollidesWith(RectangleF boundingBox, Action<CollisionInfo> onCollision)
|
||||
{
|
||||
var sx = (int)(boundingBox.Left / CellWidth);
|
||||
var sy = (int)(boundingBox.Top / CellHeight);
|
||||
var ex = (int)((boundingBox.Right / CellWidth) + 1);
|
||||
var ey = (int)((boundingBox.Bottom / CellHeight) + 1);
|
||||
|
||||
for (var y = sy; y < ey; y++)
|
||||
foreach (var cell in GetCellsOverlappingRectangle(boundingBox))
|
||||
{
|
||||
for (var x = sx; x < ex; x++)
|
||||
if (cell.Flag == CollisionGridCellFlag.Empty)
|
||||
continue;
|
||||
|
||||
var cellRectangle = GetCellRectangle(cell.Column, cell.Row);
|
||||
var intersectingRectangle = RectangleF.Intersect(cellRectangle.ToRectangleF(), boundingBox);
|
||||
|
||||
if (intersectingRectangle.IsEmpty)
|
||||
continue;
|
||||
|
||||
var collisionInfo = new CollisionInfo
|
||||
{
|
||||
if (GetDataAt(x, y) == 0)
|
||||
continue;
|
||||
Row = cell.Row,
|
||||
Column = cell.Column,
|
||||
IntersectingRectangle = intersectingRectangle,
|
||||
CellRectangle = cellRectangle
|
||||
};
|
||||
|
||||
var cellRectangle = GetCellRectangle(x, y);
|
||||
var intersectingRectangle = RectangleF.Intersect(cellRectangle.ToRectangleF(), boundingBox);
|
||||
|
||||
if (intersectingRectangle.IsEmpty)
|
||||
continue;
|
||||
|
||||
var collisionInfo = new CollisionInfo
|
||||
{
|
||||
Row = y,
|
||||
Column = x,
|
||||
IntersectingRectangle = intersectingRectangle,
|
||||
CellRectangle = cellRectangle
|
||||
};
|
||||
|
||||
onCollision(collisionInfo);
|
||||
}
|
||||
onCollision(collisionInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class CollisionInfo
|
||||
{
|
||||
public int Column { get; internal set; }
|
||||
public int Row { get; internal set; }
|
||||
public RectangleF IntersectingRectangle { get; internal set; }
|
||||
public Rectangle CellRectangle { get; internal set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
namespace MonoGame.Extended.Collisions
|
||||
{
|
||||
public class CollisionGridCell
|
||||
{
|
||||
public CollisionGridCell(int column, int row, int data)
|
||||
{
|
||||
Column = column;
|
||||
Row = row;
|
||||
Data = data;
|
||||
Flag = data == 0 ? CollisionGridCellFlag.Empty : CollisionGridCellFlag.Solid;
|
||||
}
|
||||
|
||||
public int Column { get; private set; }
|
||||
public int Row { get; private set; }
|
||||
public int Data { get; private set; }
|
||||
public object Tag { get; set; }
|
||||
public CollisionGridCellFlag Flag { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace MonoGame.Extended.Collisions
|
||||
{
|
||||
public enum CollisionGridCellFlag
|
||||
{
|
||||
Empty,
|
||||
Solid,
|
||||
Interesting
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using MonoGame.Extended.Shapes;
|
||||
|
||||
namespace MonoGame.Extended.Collisions
|
||||
{
|
||||
public class CollisionInfo
|
||||
{
|
||||
public int Column { get; internal set; }
|
||||
public int Row { get; internal set; }
|
||||
public RectangleF IntersectingRectangle { get; internal set; }
|
||||
public Rectangle CellRectangle { get; internal set; }
|
||||
}
|
||||
}
|
||||
@@ -20,14 +20,14 @@ namespace MonoGame.Extended.Collisions
|
||||
private readonly List<CollisionBody> _bodies;
|
||||
private CollisionGrid _grid;
|
||||
|
||||
public CollisionBody CreateBody(ICollidable collidable)
|
||||
public CollisionBody CreateBody(IDynamicCollidable collidable)
|
||||
{
|
||||
var body = new CollisionBody(collidable);
|
||||
_bodies.Add(body);
|
||||
return body;
|
||||
}
|
||||
|
||||
public CollisionGrid CreateGrid(byte[] data, int columns, int rows, int cellWidth, int cellHeight)
|
||||
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");
|
||||
@@ -46,7 +46,10 @@ namespace MonoGame.Extended.Collisions
|
||||
body.Position += body.Velocity * deltaTime;
|
||||
|
||||
if(_grid != null)
|
||||
_grid.CollidesWith(body.GetAxisAlignedBoundingBox(), body.OnCollision);
|
||||
{
|
||||
var boundingBox = body.GetAxisAlignedBoundingBox();
|
||||
_grid.CollidesWith(boundingBox, body.OnCollision);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-2
@@ -5,9 +5,13 @@ namespace MonoGame.Extended.Collisions
|
||||
{
|
||||
public interface ICollidable
|
||||
{
|
||||
Vector2 Position { get; set; }
|
||||
Vector2 Velocity { get; set; }
|
||||
RectangleF GetAxisAlignedBoundingBox();
|
||||
void OnCollision(CollisionInfo collisionInfo);
|
||||
}
|
||||
|
||||
public interface IDynamicCollidable : ICollidable
|
||||
{
|
||||
Vector2 Position { get; set; }
|
||||
Vector2 Velocity { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ namespace MonoGame.Extended.Maps.Tiled
|
||||
public static CollisionGrid CreateGrid(this CollisionWorld world, TiledTileLayer tileLayer)
|
||||
{
|
||||
var data = tileLayer.Tiles
|
||||
.Select(t => (byte)t.Id)
|
||||
.Select(t => t.Id)
|
||||
.ToArray();
|
||||
|
||||
return world.CreateGrid(data, tileLayer.Width, tileLayer.Height, tileLayer.TileWidth, tileLayer.TileHeight);
|
||||
|
||||
@@ -40,8 +40,11 @@
|
||||
<Compile Include="BitmapFonts\BitmapFontRegion.cs" />
|
||||
<Compile Include="Collisions\CollisionBody.cs" />
|
||||
<Compile Include="Collisions\CollisionGrid.cs" />
|
||||
<Compile Include="Collisions\CollisionGridCell.cs" />
|
||||
<Compile Include="Collisions\CollisionGridCellFlag.cs" />
|
||||
<Compile Include="Collisions\CollisionInfo.cs" />
|
||||
<Compile Include="Collisions\CollisionWorld.cs" />
|
||||
<Compile Include="Collisions\ICollidable.cs" />
|
||||
<Compile Include="Collisions\IDynamicCollidable.cs" />
|
||||
<Compile Include="Content\ContentManagerExtensions.cs" />
|
||||
<Compile Include="Camera2D.cs" />
|
||||
<Compile Include="Content\ContentReaderExtensions.cs" />
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Sandbox
|
||||
Dying
|
||||
}
|
||||
|
||||
public class Zombie : IUpdate, ICollidable
|
||||
public class Zombie : IUpdate, IDynamicCollidable
|
||||
{
|
||||
public Zombie(TextureAtlas textureAtlas)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user