diff --git a/Game/Physics2D/Abstract/ICollider2D.cs b/Game/Physics2D/Abstract/ICollider2D.cs new file mode 100644 index 0000000..730d7d0 --- /dev/null +++ b/Game/Physics2D/Abstract/ICollider2D.cs @@ -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? OnCollision { get; set; } + + Vector2 OffsetPosition { get; set; } + Vector2 OffsetScale { get; set; } + float OffsetRotation { get; set; } + + IReadOnlyList Vertices { get; } + + bool CheckCollision(ICollider2D collider); + + void RecalculateVertices(); +} diff --git a/Game/Physics2D/Abstract/ICollisionResolver2D.cs b/Game/Physics2D/Abstract/ICollisionResolver2D.cs new file mode 100644 index 0000000..83d54b4 --- /dev/null +++ b/Game/Physics2D/Abstract/ICollisionResolver2D.cs @@ -0,0 +1,6 @@ +namespace Syntriax.Engine.Physics2D.Abstract; + +public interface ICollisionResolver2D +{ + void ResolveCollision(ICollider2D colliderA, ICollider2D colliderB); +} diff --git a/Game/Physics2D/Abstract/IPhysicsEngine2D.cs b/Game/Physics2D/Abstract/IPhysicsEngine2D.cs new file mode 100644 index 0000000..aed1d10 --- /dev/null +++ b/Game/Physics2D/Abstract/IPhysicsEngine2D.cs @@ -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); +} diff --git a/Game/Physics2D/Abstract/IPhysicsMaterial2D.cs b/Game/Physics2D/Abstract/IPhysicsMaterial2D.cs new file mode 100644 index 0000000..266545d --- /dev/null +++ b/Game/Physics2D/Abstract/IPhysicsMaterial2D.cs @@ -0,0 +1,7 @@ +namespace Syntriax.Engine.Physics2D.Abstract; + +public interface IPhysicsMaterial2D +{ + float Friction { get; set; } + float Restitution { get; set; } +} diff --git a/Game/Physics2D/Abstract/IRigidBody2D.cs b/Game/Physics2D/Abstract/IRigidBody2D.cs new file mode 100644 index 0000000..0881c48 --- /dev/null +++ b/Game/Physics2D/Abstract/IRigidBody2D.cs @@ -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; } +} diff --git a/Game/Physics2D/Collider2DBehaviourBase.cs b/Game/Physics2D/Collider2DBehaviourBase.cs new file mode 100644 index 0000000..6706751 --- /dev/null +++ b/Game/Physics2D/Collider2DBehaviourBase.cs @@ -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? OnTransformAssigned { get => GameObject.OnTransformAssigned; set => GameObject.OnTransformAssigned = value; } + public Action? 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 Vertices { get; } +} diff --git a/Game/Physics2D/Collider2DBox.cs b/Game/Physics2D/Collider2DBox.cs new file mode 100644 index 0000000..930604b --- /dev/null +++ b/Game/Physics2D/Collider2DBox.cs @@ -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; + + +// } +// } diff --git a/Game/Physics2D/PhysicsEngine2D.cs b/Game/Physics2D/PhysicsEngine2D.cs new file mode 100644 index 0000000..1cd722f --- /dev/null +++ b/Game/Physics2D/PhysicsEngine2D.cs @@ -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 rigidBodies = new List(32); + private IList colliders = new List(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()) + 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); + } +} diff --git a/Game/Physics2D/RigidBody2D.cs b/Game/Physics2D/RigidBody2D.cs new file mode 100644 index 0000000..efc384d --- /dev/null +++ b/Game/Physics2D/RigidBody2D.cs @@ -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? 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); +}