attempt to introduce a collision world

This commit is contained in:
Dylan Wilson
2015-10-15 23:00:08 +10:00
parent 2d16a436ac
commit 7387a8f872
8 changed files with 165 additions and 27 deletions
@@ -0,0 +1,37 @@
using Microsoft.Xna.Framework;
using MonoGame.Extended.Shapes;
namespace MonoGame.Extended.Collisions
{
public class CollisionBody : ICollidable
{
public CollisionBody(ICollidable target)
{
_target = target;
}
private readonly ICollidable _target;
public Vector2 Velocity
{
get { return _target.Velocity; }
set { _target.Velocity = value; }
}
public Vector2 Position
{
get { return _target.Position; }
set { _target.Position = value; }
}
public RectangleF GetAxisAlignedBoundingBox()
{
return _target.GetAxisAlignedBoundingBox();
}
public void OnCollision(CollisionInfo collisionInfo)
{
_target.OnCollision(collisionInfo);
}
}
}
@@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
namespace MonoGame.Extended.Collisions
{
public class CollisionWorld : IDisposable, IUpdate
{
public CollisionWorld(Vector2 gravity)
{
_gravity = gravity;
_bodies = new List<CollisionBody>();
}
public void Dispose()
{
}
private readonly Vector2 _gravity;
private readonly List<CollisionBody> _bodies;
private CollisionGrid _grid;
public CollisionBody CreateBody(ICollidable collidable)
{
var body = new CollisionBody(collidable);
_bodies.Add(body);
return body;
}
public CollisionGrid CreateGrid(byte[] 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;
}
public void Update(GameTime gameTime)
{
var deltaTime = (float)gameTime.ElapsedGameTime.TotalSeconds;
foreach (var body in _bodies)
{
body.Velocity += _gravity * deltaTime;
body.Position += body.Velocity * deltaTime;
if(_grid != null)
_grid.CollidesWith(body.GetAxisAlignedBoundingBox(), body.OnCollision);
}
}
}
}
@@ -0,0 +1,13 @@
using Microsoft.Xna.Framework;
using MonoGame.Extended.Shapes;
namespace MonoGame.Extended.Collisions
{
public interface ICollidable
{
Vector2 Position { get; set; }
Vector2 Velocity { get; set; }
RectangleF GetAxisAlignedBoundingBox();
void OnCollision(CollisionInfo collisionInfo);
}
}
@@ -0,0 +1,17 @@
using System.Linq;
using MonoGame.Extended.Collisions;
namespace MonoGame.Extended.Maps.Tiled
{
public static class CollisionWorldExtensions
{
public static CollisionGrid CreateGrid(this CollisionWorld world, TiledTileLayer tileLayer)
{
var data = tileLayer.Tiles
.Select(t => (byte)t.Id)
.ToArray();
return world.CreateGrid(data, tileLayer.Width, tileLayer.Height, tileLayer.TileWidth, tileLayer.TileHeight);
}
}
}
@@ -31,6 +31,16 @@ namespace MonoGame.Extended.Maps.Tiled
get { return _tiles; }
}
public int TileWidth
{
get { return _map.TileWidth; }
}
public int TileHeight
{
get { return _map.TileHeight; }
}
private TiledTile[] CreateTiles(int[] data)
{
var tiles = new TiledTile[data.Length];
@@ -38,7 +38,10 @@
<Compile Include="BitmapFonts\BitmapFontExtensions.cs" />
<Compile Include="BitmapFonts\BitmapFontReader.cs" />
<Compile Include="BitmapFonts\BitmapFontRegion.cs" />
<Compile Include="Collisions\CollisionBody.cs" />
<Compile Include="Collisions\CollisionGrid.cs" />
<Compile Include="Collisions\CollisionWorld.cs" />
<Compile Include="Collisions\ICollidable.cs" />
<Compile Include="Content\ContentManagerExtensions.cs" />
<Compile Include="Camera2D.cs" />
<Compile Include="Content\ContentTypeReaderHelper.cs" />
@@ -62,6 +65,7 @@
<Compile Include="IRotatable.cs" />
<Compile Include="IScalable.cs" />
<Compile Include="IUpdate.cs" />
<Compile Include="Maps\Tiled\CollisionWorldExtensions.cs" />
<Compile Include="Maps\Tiled\TiledMapOrientation.cs" />
<Compile Include="Shapes\Circle.cs" />
<Compile Include="Shapes\RectangleF.cs" />
+26 -21
View File
@@ -1,6 +1,4 @@
using System;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using MonoGame.Extended;
@@ -27,8 +25,9 @@ namespace Sandbox
private FramesPerSecondCounter _fpsCounter;
private SpriteAnimator _spriteAnimator;
private Zombie _zombie;
private CollisionGrid _collisionGrid;
private Point _mousePoint;
//private CollisionGrid _collisionGrid;
//private Point _mousePoint;
private readonly CollisionWorld _world;
public SandboxGame()
{
@@ -37,6 +36,15 @@ namespace Sandbox
IsMouseVisible = true;
Window.Position = new Point(50, 50);
Window.Title = string.Format("MonoGame.Extended - {0}", GetType().Name);
_world = new CollisionWorld(new Vector2(0, 900));
}
protected override void Dispose(bool disposing)
{
_world.Dispose();
base.Dispose(disposing);
}
protected override void Initialize()
@@ -63,12 +71,8 @@ namespace Sandbox
_spriteBatch = new SpriteBatch(GraphicsDevice);
_bitmapFont = Content.Load<BitmapFont>("Fonts/courier-new-32");
_tiledMap = Content.Load<TiledMap>("Tilesets/level01");
var collisionData = _tiledMap
.GetLayer<TiledTileLayer>("Tile Layer 1")
.Tiles
.Select(t => (byte) t.Id)
.ToArray();
_collisionGrid = new CollisionGrid(collisionData, _tiledMap.Width, _tiledMap.Height, _tiledMap.TileWidth, _tiledMap.TileHeight);
_world.CreateGrid(_tiledMap.GetLayer<TiledTileLayer>("Tile Layer 1"));
var fireballTexture = Content.Load<Texture2D>("Sprites/fireball");
var spriteSheetAtlas = TextureAtlas.Create(fireballTexture, 512, 197);
@@ -85,6 +89,8 @@ namespace Sandbox
{
Position = new Vector2(300, 500)
};
_world.CreateBody(_zombie);
}
protected override void UnloadContent()
@@ -97,7 +103,7 @@ namespace Sandbox
var keyboardState = Keyboard.GetState();
var mouseState = Mouse.GetState();
_mousePoint = _camera.ScreenToWorld(new Vector2(mouseState.X, mouseState.Y)).ToPoint();
//_mousePoint = _camera.ScreenToWorld(new Vector2(mouseState.X, mouseState.Y)).ToPoint();
// camera
if (keyboardState.IsKeyDown(Keys.R))
@@ -122,15 +128,14 @@ namespace Sandbox
if (keyboardState.IsKeyDown(Keys.Enter))
_zombie.Die();
_zombie.Velocity += new Vector2(0, 900) * deltaSeconds;
_zombie.Position += _zombie.Velocity * deltaSeconds;
// update must be called before collision detection
_zombie.Update(gameTime);
var boundingBox = _zombie.GetAxisAlignedBoundingBox();
_collisionGrid.CollidesWith(boundingBox, _zombie.OnCollision);
_world.Update(gameTime);
//var boundingBox = _zombie.GetAxisAlignedBoundingBox();
//_collisionGrid.CollidesWith(boundingBox, _zombie.OnCollision);
_camera.LookAt(_zombie.Position);
// fireball
@@ -156,11 +161,11 @@ namespace Sandbox
_zombie.Draw(_spriteBatch);
_spriteBatch.End();
var x = _mousePoint.X / _collisionGrid.CellWidth;
var y = _mousePoint.Y / _collisionGrid.CellHeight;
//var x = _mousePoint.X / _collisionGrid.CellWidth;
//var y = _mousePoint.Y / _collisionGrid.CellHeight;
_spriteBatch.Begin();
_spriteBatch.DrawString(_bitmapFont, string.Format("CD: {0}, {1} = {2}", x, y, _collisionGrid.GetDataAt(x, y)), new Vector2(5, 35), new Color(0.5f, 0.5f, 0.5f));
//_spriteBatch.DrawString(_bitmapFont, string.Format("CD: {0}, {1} = {2}", x, y, _collisionGrid.GetDataAt(x, y)), new Vector2(5, 35), new Color(0.5f, 0.5f, 0.5f));
_spriteBatch.DrawString(_bitmapFont, string.Format("FPS: {0} Zoom: {1}", _fpsCounter.AverageFramesPerSecond, _camera.Zoom), new Vector2(5, 5), new Color(0.5f, 0.5f, 0.5f));
_spriteBatch.End();
+5 -6
View File
@@ -18,7 +18,7 @@ namespace Sandbox
Dying
}
public class Zombie : IUpdate
public class Zombie : IUpdate, ICollidable
{
public Zombie(TextureAtlas textureAtlas)
{
@@ -85,9 +85,7 @@ namespace Sandbox
public RectangleF GetAxisAlignedBoundingBox()
{
const float heightOffset = 52;
var spriteRectangle = _sprite.GetBoundingRectangle();
return new RectangleF(spriteRectangle.X, spriteRectangle.Y + heightOffset, spriteRectangle.Width, spriteRectangle.Height - heightOffset);
return _sprite.GetBoundingRectangle();
}
public Vector2 Position
@@ -102,8 +100,9 @@ namespace Sandbox
_animator.Update(gameTime);
if(State == ZombieState.Walking)
Position += new Vector2(200f * _direction, 0) * (float)gameTime.ElapsedGameTime.TotalSeconds;
Velocity = State == ZombieState.Walking
? new Vector2(200f*_direction, Velocity.Y)
: new Vector2(0, Velocity.Y);
}
public void Draw(SpriteBatch spriteBatch)