mirror of
https://github.com/AlexMacocian/MonoGame.Extended.git
synced 2026-07-25 08:22:15 +00:00
improved and simplified collision detection in the platformer demo
This commit is contained in:
@@ -11,10 +11,10 @@ namespace Platformer.Collisions
|
||||
[EntityComponent]
|
||||
public class Body
|
||||
{
|
||||
public BodyType BodyType { get; set; } = BodyType.Static;
|
||||
public Vector2 Position { get; set; }
|
||||
public BodyType BodyType = BodyType.Static;
|
||||
public Vector2 Position;
|
||||
public Vector2 Velocity;
|
||||
public AABB BoundingBox => new AABB(Position - Size / 2f, Position + Size / 2f);
|
||||
public Vector2 Size { get; set; }
|
||||
public Vector2 Size;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,13 +17,9 @@ namespace Platformer.Collisions
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool AabbAabb(Body bodyA, Body bodyB, out Manifold manifold)
|
||||
public static bool AabbAabb(AABB aBox, AABB bBox, Vector2 vector, out Manifold manifold)
|
||||
{
|
||||
manifold = new Manifold {BodyA = bodyA, BodyB = bodyB};
|
||||
|
||||
var aBox = bodyA.BoundingBox;
|
||||
var bBox = bodyB.BoundingBox;
|
||||
var vector = bodyA.Position - bodyB.Position;
|
||||
manifold = new Manifold();
|
||||
|
||||
// Calculate half extents along x axis
|
||||
var axExtent = (aBox.Max.X - aBox.Min.X) / 2f;
|
||||
|
||||
@@ -4,8 +4,6 @@ namespace Platformer.Collisions
|
||||
{
|
||||
public struct Manifold
|
||||
{
|
||||
public Body BodyA;
|
||||
public Body BodyB;
|
||||
public float Penetration;
|
||||
public Vector2 Normal;
|
||||
public Vector2 Overlap;
|
||||
|
||||
@@ -1,56 +1,67 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace Platformer.Collisions
|
||||
{
|
||||
public struct CollisionPair
|
||||
{
|
||||
public Body BodyA;
|
||||
public Body BodyB;
|
||||
}
|
||||
|
||||
public class World
|
||||
{
|
||||
public World(Vector2 gravity)
|
||||
{
|
||||
Gravity = gravity;
|
||||
Bodies = new List<Body>();
|
||||
}
|
||||
|
||||
private readonly List<CollisionPair> _collisionPairs = new List<CollisionPair>();
|
||||
|
||||
public Vector2 Gravity { get; set; }
|
||||
public List<Body> Bodies { get; }
|
||||
public Action<Manifold> OnCollision { get; set; }
|
||||
|
||||
private readonly List<Body> _dynamicBodies = new List<Body>();
|
||||
private readonly List<Body> _staticBodies = new List<Body>();
|
||||
|
||||
public void AddBody(Body body)
|
||||
{
|
||||
if (body.BodyType == BodyType.Dynamic)
|
||||
_dynamicBodies.Add(body);
|
||||
else
|
||||
_staticBodies.Add(body);
|
||||
}
|
||||
|
||||
public void RemoveBody(Body body)
|
||||
{
|
||||
if (body.BodyType == BodyType.Dynamic)
|
||||
_dynamicBodies.Remove(body);
|
||||
else
|
||||
_staticBodies.Remove(body);
|
||||
}
|
||||
|
||||
public void Update(float deltaTime)
|
||||
{
|
||||
var dynamicBodies = Bodies.Where(b => b.BodyType == BodyType.Dynamic).ToArray();
|
||||
|
||||
foreach (var body in dynamicBodies)
|
||||
{
|
||||
// apply gravity (and other forces?)
|
||||
foreach (var body in _dynamicBodies)
|
||||
body.Velocity += Gravity;
|
||||
body.Position += body.Velocity * deltaTime;
|
||||
}
|
||||
|
||||
foreach (var bodyB in dynamicBodies)
|
||||
foreach (var body in _dynamicBodies)
|
||||
{
|
||||
foreach (var bodyA in Bodies.Where(b => b.BodyType == BodyType.Static))
|
||||
body.Position.X += body.Velocity.X * deltaTime;
|
||||
ResolveCollisions(body);
|
||||
|
||||
body.Position.Y += body.Velocity.Y * deltaTime;
|
||||
ResolveCollisions(body);
|
||||
}
|
||||
}
|
||||
|
||||
private void ResolveCollisions(Body dynamicBody)
|
||||
{
|
||||
foreach (var staticBody in _staticBodies)
|
||||
{
|
||||
var vector = staticBody.Position - dynamicBody.Position;
|
||||
|
||||
if (CollisionTester.AabbAabb(dynamicBody.BoundingBox, staticBody.BoundingBox, vector, out var manifold))
|
||||
{
|
||||
if (bodyA != bodyB && CollisionTester.AabbAabb(bodyA.BoundingBox, bodyB.BoundingBox))
|
||||
_collisionPairs.Add(new CollisionPair {BodyA = bodyA, BodyB = bodyB});
|
||||
dynamicBody.Position -= manifold.Normal * manifold.Penetration;
|
||||
dynamicBody.Velocity = dynamicBody.Velocity * new Vector2(Math.Abs(manifold.Normal.Y), Math.Abs(manifold.Normal.X));
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var collisionPair in _collisionPairs)
|
||||
{
|
||||
if (CollisionTester.AabbAabb(collisionPair.BodyA, collisionPair.BodyB, out var manifold))
|
||||
OnCollision?.Invoke(manifold);
|
||||
}
|
||||
|
||||
_collisionPairs.Clear();
|
||||
// TODO: Dynamic bodies colliding with dynamic bodies.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
<tileset firstgid="1" source="tileset.tsx"/>
|
||||
<layer name="Tile Layer 1" width="25" height="15">
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJzFlDsSwCAIBTFgkftfOA0FwwxPFKPFNvp0/dKIqB3gmUAmcyuOnvCIyXmHKDwY7/EZNn2RA63TZhhkKw4/D9pzdB+Z80a8CnJUuenI/h3UVgW9g521wL65rux2RJ6/aps9uxP1NMMHET8C2w==
|
||||
eJy9lDsSACEIQ1Hw/le2scgwaxb8Fa/RaPgoRUTKA2oCS+pWPFrAx0DnPWygP+c9XqOwN/NgcaJGiXbHw9/Dcp71I1LvDCs9Z+iI8aYHyyP6d9jaLuwdnJwF+OYa1P30zPnyuTXbsHYv5mmEDqaoArU=
|
||||
</data>
|
||||
</layer>
|
||||
</map>
|
||||
|
||||
@@ -13,19 +13,19 @@ namespace Platformer.Systems
|
||||
|
||||
public WorldSystem()
|
||||
{
|
||||
_world = new World(new Vector2(0, 60)) {OnCollision = OnCollision};
|
||||
_world = new World(new Vector2(0, 60));// {OnCollision = OnCollision};
|
||||
}
|
||||
|
||||
public override void OnEntityAdded(Entity entity)
|
||||
{
|
||||
var body = entity.Get<Body>();
|
||||
_world.Bodies.Add(body);
|
||||
_world.AddBody(body);
|
||||
}
|
||||
|
||||
public override void OnEntityRemoved(Entity entity)
|
||||
{
|
||||
var body = entity.Get<Body>();
|
||||
_world.Bodies.Remove(body);
|
||||
_world.RemoveBody(body);
|
||||
}
|
||||
|
||||
protected override void Process(GameTime gameTime)
|
||||
@@ -40,17 +40,17 @@ namespace Platformer.Systems
|
||||
{
|
||||
}
|
||||
|
||||
private static void OnCollision(Manifold manifold)
|
||||
{
|
||||
var body = manifold.BodyB.BodyType == BodyType.Dynamic ? manifold.BodyB : manifold.BodyA;
|
||||
//private static void OnCollision(Manifold manifold)
|
||||
//{
|
||||
// var body = manifold.BodyB.BodyType == BodyType.Dynamic ? manifold.BodyB : manifold.BodyA;
|
||||
|
||||
body.Position -= manifold.Normal * manifold.Penetration;
|
||||
// body.Position -= manifold.Normal * manifold.Penetration;
|
||||
|
||||
if (manifold.Normal.Y < 0 || manifold.Normal.Y > 0)
|
||||
body.Velocity.Y = 0;
|
||||
// if (manifold.Normal.Y < 0 || manifold.Normal.Y > 0)
|
||||
// body.Velocity.Y = 0;
|
||||
|
||||
//if (manifold.Normal.X < 0 || manifold.Normal.X > 0)
|
||||
// body.Velocity = new Vector2(0, body.Velocity.Y);
|
||||
}
|
||||
// //if (manifold.Normal.X < 0 || manifold.Normal.X > 0)
|
||||
// // body.Velocity = new Vector2(0, body.Velocity.Y);
|
||||
//}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user