From ed15238dcdc094453c697a8f83d9308f6702dc21 Mon Sep 17 00:00:00 2001 From: Syntriax Date: Wed, 24 Jan 2024 19:21:53 +0300 Subject: [PATCH] BREAKING CHANGE: New ICollider --- .../Abstract/ICircleCollider2D.cs | 9 +++ Engine.Physics2D/Abstract/ICollider2D.cs | 6 +- Engine.Physics2D/Abstract/IRigidBody2D.cs | 1 + Engine.Physics2D/Abstract/IShapeCollider2D.cs | 9 +++ Engine.Physics2D/Collider2DAABBBehaviour.cs | 67 ------------------- Engine.Physics2D/Collider2DCircleBehaviour.cs | 28 ++++++++ Engine.Physics2D/Collider2DShapeBehaviour.cs | 29 ++++++++ Engine.Physics2D/Physics2D.cs | 8 +-- Engine.Physics2D/Primitives/Circle.cs | 16 +++++ Engine.Physics2D/Primitives/Shape.cs | 24 +++++++ Engine.Physics2D/RigidBody2D.cs | 3 +- 11 files changed, 123 insertions(+), 77 deletions(-) create mode 100644 Engine.Physics2D/Abstract/ICircleCollider2D.cs create mode 100644 Engine.Physics2D/Abstract/IShapeCollider2D.cs delete mode 100644 Engine.Physics2D/Collider2DAABBBehaviour.cs create mode 100644 Engine.Physics2D/Collider2DCircleBehaviour.cs create mode 100644 Engine.Physics2D/Collider2DShapeBehaviour.cs diff --git a/Engine.Physics2D/Abstract/ICircleCollider2D.cs b/Engine.Physics2D/Abstract/ICircleCollider2D.cs new file mode 100644 index 0000000..2391e53 --- /dev/null +++ b/Engine.Physics2D/Abstract/ICircleCollider2D.cs @@ -0,0 +1,9 @@ +using Syntriax.Engine.Physics2D.Primitives; + +namespace Syntriax.Engine.Physics2D.Abstract; + +public interface ICircleCollider2D : ICollider2D +{ + Circle CircleLocal { get; set; } + Circle CircleWorld { get; } +} diff --git a/Engine.Physics2D/Abstract/ICollider2D.cs b/Engine.Physics2D/Abstract/ICollider2D.cs index a88a19f..964180c 100644 --- a/Engine.Physics2D/Abstract/ICollider2D.cs +++ b/Engine.Physics2D/Abstract/ICollider2D.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; - using Syntriax.Engine.Core; using Syntriax.Engine.Core.Abstract; @@ -9,11 +7,9 @@ namespace Syntriax.Engine.Physics2D.Abstract; public interface ICollider2D : IBehaviour, IAssignableTransform { Action? OnCollisionPreResolve { get; set; } + Action? OnCollisionResolved { get; set; } IRigidBody2D? RigidBody2D { get; } - IList Vertices { get; } - - bool CheckCollision(Vector2D point); void Recalculate(); } diff --git a/Engine.Physics2D/Abstract/IRigidBody2D.cs b/Engine.Physics2D/Abstract/IRigidBody2D.cs index 820caa6..ef8a5c2 100644 --- a/Engine.Physics2D/Abstract/IRigidBody2D.cs +++ b/Engine.Physics2D/Abstract/IRigidBody2D.cs @@ -11,4 +11,5 @@ public interface IRigidBody2D : IBehaviour, IAssignableTransform float AngularVelocity { get; set; } float Mass { get; set; } + bool IsStatic { get; set; } } diff --git a/Engine.Physics2D/Abstract/IShapeCollider2D.cs b/Engine.Physics2D/Abstract/IShapeCollider2D.cs new file mode 100644 index 0000000..2cc5218 --- /dev/null +++ b/Engine.Physics2D/Abstract/IShapeCollider2D.cs @@ -0,0 +1,9 @@ +using Syntriax.Engine.Physics2D.Primitives; + +namespace Syntriax.Engine.Physics2D.Abstract; + +public interface IShapeCollider2D : ICollider2D +{ + Shape ShapeLocal { get; set; } + Shape ShapeWorld { get; } +} diff --git a/Engine.Physics2D/Collider2DAABBBehaviour.cs b/Engine.Physics2D/Collider2DAABBBehaviour.cs deleted file mode 100644 index 8073e64..0000000 --- a/Engine.Physics2D/Collider2DAABBBehaviour.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System; -using System.Collections.Generic; -using Engine.Physics2D; -using Syntriax.Engine.Core; -using Syntriax.Engine.Core.Abstract; -using Syntriax.Engine.Physics2D.Abstract; -using Syntriax.Engine.Physics2D.Primitives; - -namespace Syntriax.Engine.Physics2D; - -public class Collider2DAABBBehaviour : BehaviourOverride, ICollider2D -{ - public AABB AABBLocal { get; set; } = null!; - public AABB AABBWorld { get; private set; } = null!; - - private IRigidBody2D? _rigidBody2D = null; - private List _vertices = new List(4); - - public IRigidBody2D? RigidBody2D - { - get - { - if (_rigidBody2D is null) - BehaviourController.TryGetBehaviour(out _rigidBody2D); - - return _rigidBody2D; - } - } - - public Action? OnCollisionPreResolve { get; set; } = null; - - public Action? OnTransformAssigned { get => GameObject.OnTransformAssigned; set => GameObject.OnTransformAssigned = value; } - ITransform IAssignableTransform.Transform => Transform; - public bool Assign(ITransform transform) => GameObject.Assign(transform); - - public IList Vertices => _vertices; - - public bool CheckCollision(Vector2D point) - { - return AABBWorld.Overlaps(point); - } - - public void Recalculate() - { - AABBWorld = new AABB( - AABBLocal.LowerBoundary.Scale(Transform.Scale) + Transform.Position, - AABBLocal.UpperBoundary.Scale(Transform.Scale) + Transform.Position - ); - - Vertices.Clear(); - Vertices.Add(AABBWorld.LowerBoundary); - Vertices.Add(new Vector2D(AABBWorld.LowerBoundary.X, AABBWorld.UpperBoundary.Y)); - Vertices.Add(AABBWorld.UpperBoundary); - Vertices.Add(new Vector2D(AABBWorld.UpperBoundary.X, AABBWorld.LowerBoundary.Y)); - } - public Collider2DAABBBehaviour(Vector2D lowerBoundary, Vector2D upperBoundary) - { - AABBLocal = new AABB(lowerBoundary, upperBoundary); - AABBWorld = new AABB(lowerBoundary, upperBoundary); - } - - public Collider2DAABBBehaviour() - { - AABBLocal = new(Vector2D.Zero, Vector2D.Zero); - AABBWorld = new(Vector2D.Zero, Vector2D.Zero); - } -} diff --git a/Engine.Physics2D/Collider2DCircleBehaviour.cs b/Engine.Physics2D/Collider2DCircleBehaviour.cs new file mode 100644 index 0000000..7a68e68 --- /dev/null +++ b/Engine.Physics2D/Collider2DCircleBehaviour.cs @@ -0,0 +1,28 @@ +using System; + +using Syntriax.Engine.Core; +using Syntriax.Engine.Core.Abstract; +using Syntriax.Engine.Physics2D.Abstract; +using Syntriax.Engine.Physics2D.Primitives; + +namespace Syntriax.Engine.Physics2D; + +public class Collider2DCircleBehaviour : BehaviourOverride, ICircleCollider2D +{ + public Action? OnCollisionPreResolve { get; set; } = null; + public Action? OnCollisionResolved { get; set; } = null; + + public Action? OnTransformAssigned { get; set; } = null; + + + public Circle CircleWorld { get; protected set; } = new(Vector2D.Zero, 1f); + public Circle CircleLocal { get; set; } = new(Vector2D.Zero, 1f); + public IRigidBody2D? RigidBody2D { get; set; } = null; + + + ITransform IAssignableTransform.Transform => GameObject.Transform; + + public bool Assign(ITransform transform) => GameObject.Assign(transform); + + public virtual void Recalculate() => CircleWorld = Transform.TransformCircle(CircleLocal).Displace(Transform.Position); +} diff --git a/Engine.Physics2D/Collider2DShapeBehaviour.cs b/Engine.Physics2D/Collider2DShapeBehaviour.cs new file mode 100644 index 0000000..159fa02 --- /dev/null +++ b/Engine.Physics2D/Collider2DShapeBehaviour.cs @@ -0,0 +1,29 @@ +using System; + +using Syntriax.Engine.Core; +using Syntriax.Engine.Core.Abstract; +using Syntriax.Engine.Physics2D.Abstract; +using Syntriax.Engine.Physics2D.Primitives; + +namespace Syntriax.Engine.Physics2D; + +public class Collider2DShapeBehaviour : BehaviourOverride, IShapeCollider2D +{ + public Action? OnCollisionPreResolve { get; set; } = null; + public Action? OnCollisionResolved { get; set; } = null; + + public Action? OnTransformAssigned { get; set; } = null; + + + public Shape ShapeWorld => _shapeWorld; + public Shape ShapeLocal { get; set; } = new([new(1f, 1f), new(-1f, 1f), new(-1f, -1f), new(1f, -1f)]); + public IRigidBody2D? RigidBody2D { get; set; } = null; + + protected Shape _shapeWorld = new([new(1f, 1f), new(-1f, 1f), new(-1f, -1f), new(1f, -1f)]); + + ITransform IAssignableTransform.Transform => GameObject.Transform; + + public bool Assign(ITransform transform) => GameObject.Assign(transform); + + public virtual void Recalculate() => Transform.TransformShape(ShapeLocal, ref _shapeWorld); +} diff --git a/Engine.Physics2D/Physics2D.cs b/Engine.Physics2D/Physics2D.cs index acf0fc3..a9f722b 100644 --- a/Engine.Physics2D/Physics2D.cs +++ b/Engine.Physics2D/Physics2D.cs @@ -10,7 +10,7 @@ public static partial class Physics2D { public static bool Overlaps(this Circle left, Circle right) { - float distanceSquared = left.Position.FromTo(right.Position).LengthSquared(); + float distanceSquared = left.Center.FromTo(right.Center).LengthSquared(); float radiusSumSquared = left.RadiusSquared + right.RadiusSquared; return distanceSquared < radiusSumSquared; @@ -18,7 +18,7 @@ public static partial class Physics2D public static bool Overlaps(this Circle left, Circle right, out Vector2D normal, out float depth) { - Vector2D distanceVector = left.Position.FromTo(right.Position); + Vector2D distanceVector = left.Center.FromTo(right.Center); float distanceSquared = distanceVector.LengthSquared(); float radiusSumSquared = left.RadiusSquared + right.RadiusSquared; bool isOverlapping = distanceSquared < radiusSumSquared; @@ -32,10 +32,10 @@ public static partial class Physics2D return isOverlapping; } - public static bool Overlaps(this Circle circle, Vector2D point) => circle.Position.FromTo(point).LengthSquared() <= circle.RadiusSquared; + public static bool Overlaps(this Circle circle, Vector2D point) => circle.Center.FromTo(point).LengthSquared() <= circle.RadiusSquared; public static bool Overlaps(this Circle circle, Vector2D point, out Vector2D normal, out float depth) { - Vector2D distanceVector = circle.Position.FromTo(point); + Vector2D distanceVector = circle.Center.FromTo(point); float distanceSquared = distanceVector.LengthSquared(); float radiusSquared = circle.RadiusSquared; bool isOverlapping = distanceSquared < radiusSquared; diff --git a/Engine.Physics2D/Primitives/Circle.cs b/Engine.Physics2D/Primitives/Circle.cs index 9cd8073..360fdf5 100644 --- a/Engine.Physics2D/Primitives/Circle.cs +++ b/Engine.Physics2D/Primitives/Circle.cs @@ -1,4 +1,5 @@ using Syntriax.Engine.Core; +using Syntriax.Engine.Core.Abstract; namespace Syntriax.Engine.Physics2D.Primitives; @@ -7,11 +8,26 @@ public record Circle(Vector2D Center, float Radius) public float RadiusSquared => Radius * Radius; public float Diameter => 2f * Radius; + public static Circle SetCenter(Circle circle, Vector2D center) => new(center, circle.Radius); + public static Circle SetRadius(Circle circle, float radius) => new(circle.Center, radius); + + public static Circle Displace(Circle circle, Vector2D displaceVector) => new(circle.Center + displaceVector, circle.Radius); + + public static Circle TransformCircle(ITransform transform, Circle circle) + => new(transform.TransformVector2D(circle.Center), circle.Radius * transform.Scale.Magnitude); + public static bool ApproximatelyEquals(Circle left, Circle right) => left.Center.ApproximatelyEquals(right.Center) && left.Radius.ApproximatelyEquals(right.Radius); } public static class CircleExtensions { + public static Circle SetCenter(this Circle circle, Vector2D center) => Circle.SetCenter(circle, center); + public static Circle SetRadius(this Circle circle, float radius) => Circle.SetRadius(circle, radius); + + public static Circle Displace(this Circle circle, Vector2D displaceVector) => Circle.Displace(circle, displaceVector); + + public static Circle TransformCircle(this ITransform transform, Circle circle) => TransformCircle(transform, circle); + public static bool ApproximatelyEquals(this Circle left, Circle right) => Circle.ApproximatelyEquals(left, right); } diff --git a/Engine.Physics2D/Primitives/Shape.cs b/Engine.Physics2D/Primitives/Shape.cs index dbd3987..08570d2 100644 --- a/Engine.Physics2D/Primitives/Shape.cs +++ b/Engine.Physics2D/Primitives/Shape.cs @@ -3,6 +3,7 @@ using System.Collections; using System.Collections.Generic; using Syntriax.Engine.Core; +using Syntriax.Engine.Core.Abstract; namespace Syntriax.Engine.Physics2D.Primitives; @@ -51,6 +52,26 @@ public record Shape(IList Vertices) : IEnumerable return lines; } + public static Shape TransformShape(Shape shape, ITransform transform) + { + List vertices = new(shape.Vertices.Count); + + int count = shape.Vertices.Count; + for (int i = 0; i < count; i++) + vertices.Add(transform.TransformVector2D(shape[i])); + + return new Shape(vertices); + } + + public static void TransformShape(Shape from, ITransform transform, ref Shape to) + { + to.Vertices.Clear(); + + int count = from.Vertices.Count; + for (int i = 0; i < count; i++) + to.Vertices.Add(transform.TransformVector2D(from[i])); + } + public static bool ApproximatelyEquals(Shape left, Shape right) { if (left.Vertices.Count != right.Vertices.Count) @@ -73,5 +94,8 @@ public static class ShapeExtensions public static void ToLines(this Shape shape, IList lines) => Shape.GetLines(shape, lines); public static List ToLines(this Shape shape) => Shape.GetLines(shape); + public static Shape TransformShape(this ITransform transform, Shape shape) => Shape.TransformShape(shape, transform); + public static void TransformShape(this ITransform transform, Shape from, ref Shape to) => Shape.TransformShape(from, transform, ref to); + public static bool ApproximatelyEquals(this Shape left, Shape right) => Shape.ApproximatelyEquals(left, right); } diff --git a/Engine.Physics2D/RigidBody2D.cs b/Engine.Physics2D/RigidBody2D.cs index ed4fb4a..e2fe1da 100644 --- a/Engine.Physics2D/RigidBody2D.cs +++ b/Engine.Physics2D/RigidBody2D.cs @@ -15,7 +15,8 @@ public class RigidBody2D : BehaviourOverride, IRigidBody2D public Vector2D Velocity { get; set; } = Vector2D.Zero; public float AngularVelocity { get; set; } = 0f; - public float Mass { get; set; } = 0f; + public float Mass { get; set; } = 1f; + public bool IsStatic { get; set; } = false; ITransform IAssignableTransform.Transform => Transform;