This commit is contained in:
2025-05-30 16:05:49 +03:00
committed by Syntriax
parent 846aa75dd5
commit b5140a94de
57 changed files with 437 additions and 462 deletions

View File

@@ -44,7 +44,7 @@ public interface ICollider2D : IBehaviour
void Resolve(CollisionDetectionInformation collisionDetectionInformation);
void Trigger(ICollider2D initiator);
delegate void CollisionDetectedEventHandler(ICollider2D sender, CollisionDetectionInformation collisionDetectionInformation);
delegate void CollisionResolvedEventHandler(ICollider2D sender, CollisionDetectionInformation collisionDetectionInformation);
delegate void TriggeredEventHandler(ICollider2D sender, ICollider2D initiatorCollider);
readonly record struct CollisionDetectedArguments(ICollider2D sender, CollisionDetectionInformation collisionDetectionInformation);
readonly record struct CollisionResolvedArguments(ICollider2D sender, CollisionDetectionInformation collisionDetectionInformation);
readonly record struct TriggeredArguments(ICollider2D sender, ICollider2D initiatorCollider);
}

View File

@@ -35,6 +35,6 @@ public interface IPhysicsEngine2D
/// <param name="deltaTime">The time step.</param>
void StepIndividual(IRigidBody2D rigidBody, float deltaTime);
delegate void PhysicsIterationEventHandler(IPhysicsEngine2D sender, float iterationDeltaTime);
delegate void PhysicsStepEventHandler(IPhysicsEngine2D sender, float stepDeltaTime);
readonly record struct PhysicsIterationArguments(IPhysicsEngine2D sender, float iterationDeltaTime);
readonly record struct PhysicsStepArguments(IPhysicsEngine2D sender, float stepDeltaTime);
}

View File

@@ -4,13 +4,30 @@ namespace Syntriax.Engine.Physics2D;
public abstract class Collider2DBehaviourBase : Behaviour2D, ICollider2D
{
public Event<ICollider2D, CollisionDetectionInformation> OnCollisionDetected { get; private set; } = new();
public Event<ICollider2D, CollisionDetectionInformation> OnCollisionResolved { get; private set; } = new();
public Event<ICollider2D, ICollider2D> OnTriggered { get; private set; } = new();
public Event<ICollider2D, CollisionDetectionInformation> OnCollisionDetected { get; init; } = new();
public Event<ICollider2D, CollisionDetectionInformation> OnCollisionResolved { get; init; } = new();
public Event<ICollider2D, ICollider2D> OnTriggered { get; init; } = new();
private readonly Event<IBehaviourController, IBehaviourController.BehaviourAddedArguments>.EventHandler cachedOnBehaviourAddedToController = null!;
private readonly Event<IBehaviourController, IBehaviourController.BehaviourRemovedArguments>.EventHandler cachedOnBehaviourRemovedFromController = null!;
private readonly Event<ITransform2D, ITransform2D.PositionChangedArguments>.EventHandler cachedSetNeedsRecalculationFromPosition = null!;
private readonly Event<ITransform2D, ITransform2D.RotationChangedArguments>.EventHandler cachedSetNeedsRecalculationFromRotation = null!;
private readonly Event<ITransform2D, ITransform2D.ScaleChangedArguments>.EventHandler cachedSetNeedsRecalculationFromScale = null!;
private readonly Event<IUniverseObject, IUniverseObject.ParentChangedArguments>.EventHandler cachedUpdateRigidBody2D = null!;
protected bool NeedsRecalculation { get; set; } = true;
protected IRigidBody2D? _rigidBody2D = null;
protected Collider2DBehaviourBase()
{
cachedOnBehaviourAddedToController = OnBehaviourAddedToController;
cachedOnBehaviourRemovedFromController = OnBehaviourRemovedFromController;
cachedSetNeedsRecalculationFromPosition = SetNeedsRecalculationFromPosition;
cachedSetNeedsRecalculationFromRotation = SetNeedsRecalculationFromRotation;
cachedSetNeedsRecalculationFromScale = SetNeedsRecalculationFromScale;
cachedUpdateRigidBody2D = UpdateRigidBody2D;
}
public IRigidBody2D? RigidBody2D => _rigidBody2D;
public bool IsTrigger { get; set; } = false;
@@ -29,44 +46,44 @@ public abstract class Collider2DBehaviourBase : Behaviour2D, ICollider2D
{
BehaviourController.TryGetBehaviourInParent(out _rigidBody2D);
BehaviourController.OnBehaviourAdded.AddListener(OnBehaviourAddedToController);
BehaviourController.OnBehaviourRemoved.AddListener(OnBehaviourRemovedFromController);
BehaviourController.OnBehaviourAdded.AddListener(cachedOnBehaviourAddedToController);
BehaviourController.OnBehaviourRemoved.AddListener(cachedOnBehaviourRemovedFromController);
Transform.OnPositionChanged.AddListener(SetNeedsRecalculationFromPosition);
Transform.OnRotationChanged.AddListener(SetNeedsRecalculationFromRotation);
Transform.OnScaleChanged.AddListener(SetNeedsRecalculationFromScale);
UniverseObject.OnParentChanged.AddListener(UpdateRigidBody2D);
Transform.OnPositionChanged.AddListener(cachedSetNeedsRecalculationFromPosition);
Transform.OnRotationChanged.AddListener(cachedSetNeedsRecalculationFromRotation);
Transform.OnScaleChanged.AddListener(cachedSetNeedsRecalculationFromScale);
UniverseObject.OnParentChanged.AddListener(cachedUpdateRigidBody2D);
}
private void UpdateRigidBody2D(IUniverseObject sender, IUniverseObject? previousParent, IUniverseObject? newParent)
private void UpdateRigidBody2D(IUniverseObject sender, IUniverseObject.ParentChangedArguments arguments)
{
BehaviourController.TryGetBehaviourInParent(out _rigidBody2D);
}
private void OnBehaviourAddedToController(IBehaviourController _, IBehaviour behaviour)
private void OnBehaviourAddedToController(IBehaviourController sender, IBehaviourController.BehaviourAddedArguments arguments)
{
if (behaviour is IRigidBody2D rigidBody)
if (arguments.BehaviourAdded is IRigidBody2D rigidBody)
_rigidBody2D = rigidBody;
}
private void OnBehaviourRemovedFromController(IBehaviourController _, IBehaviour behaviour)
private void OnBehaviourRemovedFromController(IBehaviourController sender, IBehaviourController.BehaviourRemovedArguments arguments)
{
if (behaviour is IRigidBody2D _)
if (arguments.BehaviourRemoved is IRigidBody2D)
_rigidBody2D = null;
}
private void SetNeedsRecalculationFromScale(ITransform2D sender, Vector2D previousScale) => NeedsRecalculation = true;
private void SetNeedsRecalculationFromPosition(ITransform2D sender, Vector2D previousPosition) => NeedsRecalculation = true;
private void SetNeedsRecalculationFromRotation(ITransform2D sender, float previousRotation) => NeedsRecalculation = true;
private void SetNeedsRecalculationFromPosition(ITransform2D sender, ITransform2D.PositionChangedArguments arguments) => NeedsRecalculation = true;
private void SetNeedsRecalculationFromScale(ITransform2D sender, ITransform2D.ScaleChangedArguments arguments) => NeedsRecalculation = true;
private void SetNeedsRecalculationFromRotation(ITransform2D sender, ITransform2D.RotationChangedArguments arguments) => NeedsRecalculation = true;
protected override void OnFinalize()
{
BehaviourController.OnBehaviourAdded.RemoveListener(OnBehaviourAddedToController);
BehaviourController.OnBehaviourRemoved.RemoveListener(OnBehaviourRemovedFromController);
Transform.OnScaleChanged.RemoveListener(SetNeedsRecalculationFromScale);
BehaviourController.OnBehaviourAdded.RemoveListener(cachedOnBehaviourAddedToController);
BehaviourController.OnBehaviourRemoved.RemoveListener(cachedOnBehaviourRemovedFromController);
Transform.OnScaleChanged.RemoveListener(cachedSetNeedsRecalculationFromScale);
Transform.OnPositionChanged.RemoveListener(SetNeedsRecalculationFromPosition);
Transform.OnRotationChanged.RemoveListener(SetNeedsRecalculationFromRotation);
Transform.OnPositionChanged.RemoveListener(cachedSetNeedsRecalculationFromPosition);
Transform.OnRotationChanged.RemoveListener(cachedSetNeedsRecalculationFromRotation);
}
public void Detect(CollisionDetectionInformation collisionDetectionInformation) => OnCollisionDetected?.Invoke(this, collisionDetectionInformation);

View File

@@ -7,6 +7,8 @@ namespace Syntriax.Engine.Physics2D;
public class PhysicsCoroutineManager : UniverseObject
{
private readonly Event<IUniverse, IUniverse.UpdateArguments>.EventHandler cachedOnUpdate = null!;
private readonly List<IEnumerator> enumerators = [];
private IPhysicsEngine2D? physicsEngine = null;
@@ -49,7 +51,7 @@ public class PhysicsCoroutineManager : UniverseObject
universe.OnUpdate.RemoveListener(OnUpdate);
}
private void OnUpdate(IUniverse sender, UniverseTime engineTime)
private void OnUpdate(IUniverse sender, IUniverse.UpdateArguments arguments)
{
if (Universe is not IUniverse universe)
return;
@@ -61,4 +63,9 @@ public class PhysicsCoroutineManager : UniverseObject
universe.OnUpdate.RemoveListener(OnUpdate);
}
}
public PhysicsCoroutineManager()
{
cachedOnUpdate = OnUpdate;
}
}

View File

@@ -4,8 +4,10 @@ namespace Syntriax.Engine.Physics2D;
public class PhysicsEngine2D : UniverseObject, IPhysicsEngine2D
{
public Event<IPhysicsEngine2D, float> OnPhysicsIteration { get; private set; } = new();
public Event<IPhysicsEngine2D, float> OnPhysicsStep { get; private set; } = new();
public Event<IPhysicsEngine2D, float> OnPhysicsIteration { get; init; } = new();
public Event<IPhysicsEngine2D, float> OnPhysicsStep { get; init; } = new();
private readonly Event<IUniverse, IUniverse.UpdateArguments>.EventHandler cachedOnPreUpdate = null!;
private float physicsTicker = 0f;
private int _iterationPerStep = 1;
@@ -192,9 +194,9 @@ public class PhysicsEngine2D : UniverseObject, IPhysicsEngine2D
universe.OnPreUpdate.RemoveListener(OnEnginePreUpdate);
}
private void OnEnginePreUpdate(IUniverse sender, UniverseTime engineTime)
private void OnEnginePreUpdate(IUniverse sender, IUniverse.UpdateArguments arguments)
{
physicsTicker += engineTime.DeltaTime;
physicsTicker += arguments.EngineTime.DeltaTime;
while (physicsTicker >= IterationPeriod)
{
@@ -207,11 +209,15 @@ public class PhysicsEngine2D : UniverseObject, IPhysicsEngine2D
{
collisionDetector = new CollisionDetector2D();
collisionResolver = new CollisionResolver2D();
cachedOnPreUpdate = OnEnginePreUpdate;
}
public PhysicsEngine2D(ICollisionDetector2D collisionDetector, ICollisionResolver2D collisionResolver)
{
this.collisionDetector = collisionDetector;
this.collisionResolver = collisionResolver;
cachedOnPreUpdate = OnEnginePreUpdate;
}
}

View File

@@ -6,8 +6,11 @@ namespace Syntriax.Engine.Physics2D;
public class PhysicsEngine2DStandalone : IPhysicsEngine2D
{
public Event<IPhysicsEngine2D, float> OnPhysicsIteration { get; private set; } = new();
public Event<IPhysicsEngine2D, float> OnPhysicsStep { get; private set; } = new();
public Event<IPhysicsEngine2D, float> OnPhysicsIteration { get; init; } = new();
public Event<IPhysicsEngine2D, float> OnPhysicsStep { get; init; } = new();
private readonly Event<IBehaviourController, IBehaviourController.BehaviourAddedArguments>.EventHandler cachedOnBehaviourAdded = null!;
private readonly Event<IBehaviourController, IBehaviourController.BehaviourRemovedArguments>.EventHandler cachedOnBehaviourRemoved = null!;
private readonly List<IRigidBody2D> rigidBodies = new(32);
private readonly List<ICollider2D> colliders = new(64);
@@ -29,16 +32,16 @@ public class PhysicsEngine2DStandalone : IPhysicsEngine2D
foreach (ICollider2D collider2D in rigidBody.BehaviourController.GetBehaviours<ICollider2D>())
colliders.Add(collider2D);
rigidBody.BehaviourController.OnBehaviourAdded.AddListener(OnBehaviourAdded);
rigidBody.BehaviourController.OnBehaviourRemoved.AddListener(OnBehaviourRemoved);
rigidBody.BehaviourController.OnBehaviourAdded.AddListener(cachedOnBehaviourAdded);
rigidBody.BehaviourController.OnBehaviourRemoved.AddListener(cachedOnBehaviourRemoved);
}
public void RemoveRigidBody(IRigidBody2D rigidBody)
{
rigidBodies.Remove(rigidBody);
rigidBody.BehaviourController.OnBehaviourAdded.RemoveListener(OnBehaviourAdded);
rigidBody.BehaviourController.OnBehaviourRemoved.RemoveListener(OnBehaviourRemoved);
rigidBody.BehaviourController.OnBehaviourAdded.RemoveListener(cachedOnBehaviourAdded);
rigidBody.BehaviourController.OnBehaviourRemoved.RemoveListener(cachedOnBehaviourRemoved);
}
public void Step(float deltaTime)
@@ -175,17 +178,17 @@ public class PhysicsEngine2DStandalone : IPhysicsEngine2D
rigidBody.Transform.Rotation += rigidBody.AngularVelocity * intervalDeltaTime;
}
private void OnBehaviourAdded(IBehaviourController controller, IBehaviour behaviour)
private void OnBehaviourAdded(IBehaviourController sender, IBehaviourController.BehaviourAddedArguments arguments)
{
if (behaviour is not ICollider2D collider2D)
if (arguments.BehaviourAdded is not ICollider2D collider2D)
return;
colliders.Add(collider2D);
}
private void OnBehaviourRemoved(IBehaviourController controller, IBehaviour behaviour)
private void OnBehaviourRemoved(IBehaviourController sender, IBehaviourController.BehaviourRemovedArguments arguments)
{
if (behaviour is not ICollider2D collider2D)
if (arguments.BehaviourRemoved is not ICollider2D collider2D)
return;
colliders.Remove(collider2D);
@@ -195,11 +198,17 @@ public class PhysicsEngine2DStandalone : IPhysicsEngine2D
{
collisionDetector = new CollisionDetector2D();
collisionResolver = new CollisionResolver2D();
cachedOnBehaviourAdded = OnBehaviourAdded;
cachedOnBehaviourRemoved = OnBehaviourRemoved;
}
public PhysicsEngine2DStandalone(ICollisionDetector2D collisionDetector, ICollisionResolver2D collisionResolver)
{
this.collisionDetector = collisionDetector;
this.collisionResolver = collisionResolver;
cachedOnBehaviourAdded = OnBehaviourAdded;
cachedOnBehaviourRemoved = OnBehaviourRemoved;
}
}