This commit is contained in:
Syntriax 2023-11-30 17:52:09 +03:00
parent 9ec92c1beb
commit 670842c1e3
9 changed files with 222 additions and 0 deletions

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Syntriax.Engine.Core.Abstract;
namespace Syntriax.Engine.Physics2D.Abstract;
public interface ICollider2D : IBehaviour, IAssignableTransform
{
Action<ICollider2D, ICollider2D>? OnCollision { get; set; }
Vector2 OffsetPosition { get; set; }
Vector2 OffsetScale { get; set; }
float OffsetRotation { get; set; }
IReadOnlyList<Vector2> Vertices { get; }
bool CheckCollision(ICollider2D collider);
void RecalculateVertices();
}

View File

@ -0,0 +1,6 @@
namespace Syntriax.Engine.Physics2D.Abstract;
public interface ICollisionResolver2D
{
void ResolveCollision(ICollider2D colliderA, ICollider2D colliderB);
}

View File

@ -0,0 +1,11 @@
namespace Syntriax.Engine.Physics2D.Abstract;
public interface IPhysicsEngine2D
{
int IterationCount { get; set; }
void AddRigidBody(IRigidBody2D rigidBody);
void RemoveRigidBody(IRigidBody2D rigidBody);
void Step(float deltaTime);
}

View File

@ -0,0 +1,7 @@
namespace Syntriax.Engine.Physics2D.Abstract;
public interface IPhysicsMaterial2D
{
float Friction { get; set; }
float Restitution { get; set; }
}

View File

@ -0,0 +1,15 @@
using Microsoft.Xna.Framework;
using Syntriax.Engine.Core.Abstract;
namespace Syntriax.Engine.Physics2D.Abstract;
public interface IRigidBody2D : IBehaviour, IAssignableTransform
{
IPhysicsMaterial2D Material { get; set; }
Vector2 Velocity { get; set; }
float AngularVelocity { get; set; }
float Mass { get; set; }
}

View File

@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Syntriax.Engine.Core;
using Syntriax.Engine.Core.Abstract;
using Syntriax.Engine.Physics2D.Abstract;
namespace Syntriax.Engine.Physics2D;
public abstract class Collider2DBehaviourBase : BehaviourOverride, ICollider2D
{
public Action<IAssignableTransform>? OnTransformAssigned { get => GameObject.OnTransformAssigned; set => GameObject.OnTransformAssigned = value; }
public Action<ICollider2D, ICollider2D>? OnCollision { get; set; } = null;
public Vector2 OffsetPosition { get; set; } = Vector2.Zero;
public Vector2 OffsetScale { get; set; } = Vector2.One;
public float OffsetRotation { get; set; } = 0f;
ITransform IAssignableTransform.Transform => Transform;
public bool Assign(ITransform transform) => GameObject.Assign(transform);
public void RecalculateVertices()
{
throw new NotImplementedException();
}
public bool CheckCollision(ICollider2D collider)
{
return false;
OnCollision?.Invoke(this, collider);
return true;
}
public abstract IReadOnlyList<Vector2> Vertices { get; }
}

View File

@ -0,0 +1,16 @@
using System;
using Syntriax.Engine.Physics2D.Abstract;
namespace Syntriax.Engine.Physics2D;
// public class Collider2DBox : Collider2DBehaviourBase
// {
// protected override bool ProcessCollision(ICollider2D collider)
// {
// if (collider is not Collider2DBox)
// return false;
// }
// }

View File

@ -0,0 +1,78 @@
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Syntriax.Engine.Core.Abstract;
using Syntriax.Engine.Physics2D.Abstract;
namespace Syntriax.Engine.Physics2D;
public class PhysicsEngine2D : IPhysicsEngine2D
{
private IList<IRigidBody2D> rigidBodies = new List<IRigidBody2D>(32);
private IList<ICollider2D> colliders = new List<ICollider2D>(64);
private int _iterationCount = 1;
public int IterationCount { get => _iterationCount; set => _iterationCount = value < 1 ? 1 : value; }
public void AddRigidBody(IRigidBody2D rigidBody)
{
if (rigidBodies.Contains(rigidBody))
return;
rigidBodies.Add(rigidBody);
foreach (var collider2D in rigidBody.BehaviourController.GetBehaviours<ICollider2D>())
colliders.Add(collider2D);
rigidBody.BehaviourController.OnBehaviourAdded += OnBehaviourAdded;
rigidBody.BehaviourController.OnBehaviourRemoved += OnBehaviourRemoved;
}
public void RemoveRigidBody(IRigidBody2D rigidBody)
{
rigidBodies.Remove(rigidBody);
}
public void Step(float deltaTime)
{
float intervalDeltaTime = deltaTime / IterationCount;
for (int i = 0; i < IterationCount; i++)
{
foreach (var rigidBody in rigidBodies)
{
Vector2 nextPosition = rigidBody.Transform.Position;
nextPosition += rigidBody.Velocity * intervalDeltaTime;
rigidBody.Transform.Position += nextPosition;
}
for (int colliderIX = 0; colliderIX < colliders.Count; colliderIX++)
{
ICollider2D colliderX = colliders[colliderIX];
for (int colliderIY = colliderIX + 1; colliderIY < colliders.Count; colliderIY++)
if (colliderX.CheckCollision(colliders[colliderIY]))
Console.WriteLine($"Collision");
}
}
}
private void OnBehaviourAdded(IBehaviourController controller, IBehaviour behaviour)
{
if (behaviour is not ICollider2D collider2D)
return;
colliders.Add(collider2D);
}
private void OnBehaviourRemoved(IBehaviourController controller, IBehaviour behaviour)
{
if (behaviour is not ICollider2D collider2D)
return;
colliders.Remove(collider2D);
}
}

View File

@ -0,0 +1,25 @@
using System;
using Microsoft.Xna.Framework;
using Syntriax.Engine.Core;
using Syntriax.Engine.Core.Abstract;
using Syntriax.Engine.Physics2D.Abstract;
namespace Syntriax.Engine.Physics2D;
public class RigidBody2D : BehaviourOverride, IRigidBody2D
{
public Action<IAssignableTransform>? OnTransformAssigned { get => GameObject.OnTransformAssigned; set => GameObject.OnTransformAssigned = value; }
public IPhysicsMaterial2D Material { get; set; } = null!;
public Vector2 Velocity { get; set; } = Vector2.Zero;
public float AngularVelocity { get; set; } = 0f;
public float Mass { get; set; } = 0f;
ITransform IAssignableTransform.Transform => Transform;
public bool Assign(ITransform transform) => GameObject.Assign(transform);
}