14 Commits

Author SHA1 Message Date
2cf6135063 refactor: Renamed BehaviourCacher to BehaviourCollector 2024-02-09 09:43:15 +03:00
be06575f91 feat: BehaviourExtensions.FindBehaviour 2024-02-08 17:58:15 +03:00
ed6975bf24 fix: Null Reference Error on ITransform.SetParent 2024-02-07 14:24:19 +03:00
d9660c08b1 feat: Collider RigidBody Reference Update on Parent Change 2024-02-07 12:33:07 +03:00
3902f1caca feat: Parent Change Propagation to Children 2024-02-07 12:32:55 +03:00
14e3337daa feat: BehaviourControllerExtensions
- TryGetBehaviourInParent
- GetBehaviourInParent
- TryGetBehaviourInChildren
- GetBehaviourInChildren
2024-02-07 11:53:57 +03:00
f729cdc0a8 revert: refactor: ITransformWithGameObject
This reverts commit f96c58cbd4.
2024-02-07 11:45:14 +03:00
c767e1e856 docs(core): Parent & Child Methods 2024-02-06 17:42:24 +03:00
f96c58cbd4 refactor: ITransformWithGameObject 2024-02-06 17:38:11 +03:00
fed288859f feat: IAssignableGameObject to ITransform
I originally didn't want ITransform to have a reference to any IGameObject, since it didn't seem necessary to couple these two, and to make ITransform more flexible and reusable but without it we can't get a reference to the IGameObject(s) that's using that ITransform without doing some very stupid workarounds. I'll try to find a better way for this.
2024-02-06 17:32:39 +03:00
6e4c9b0ef8 feat: Transform Hierarchy System 2024-02-06 15:55:07 +03:00
b931abb735 feat: Shape to Vector2D Overlap 2024-02-06 10:56:54 +03:00
72492a9f5a docs: Basic README.md 2024-02-05 12:20:12 +03:00
2f043c19a6 feat: GameManagerExtensions.InstantiateGameObject 2024-02-05 11:20:15 +03:00
12 changed files with 440 additions and 43 deletions

View File

@@ -1,11 +1,12 @@
using System; using System;
using System.Collections.Generic;
namespace Syntriax.Engine.Core.Abstract; namespace Syntriax.Engine.Core.Abstract;
/// <summary> /// <summary>
/// Represents the transformation properties of an object such as position, scale, and rotation. /// Represents the transformation properties of an object such as position, scale, and rotation.
/// </summary> /// </summary>
public interface ITransform public interface ITransform : IAssignableGameObject, IEnumerable<ITransform>
{ {
/// <summary> /// <summary>
/// Event triggered when the <see cref="Position"/> of the <see cref="ITransform"/> changes. /// Event triggered when the <see cref="Position"/> of the <see cref="ITransform"/> changes.
@@ -23,17 +24,75 @@ public interface ITransform
Action<ITransform>? OnRotationChanged { get; set; } Action<ITransform>? OnRotationChanged { get; set; }
/// <summary> /// <summary>
/// The position of the <see cref="ITransform"/> in 2D space. /// Event triggered when the <see cref="Parent"/> of the <see cref="ITransform"/> changes. The second parameter is the old <see cref="ITransform"/>.
/// </summary>
Action<ITransform, ITransform?>? OnParentChanged { get; set; }
/// <summary>
/// Event triggered when a new <see cref="ITransform"/> is added to the <see cref="Children"/>.
/// </summary>
Action<ITransform, ITransform>? OnChildrenAdded { get; set; }
/// <summary>
/// Event triggered when an <see cref="ITransform"/> is removed from the <see cref="Children"/>.
/// </summary>
Action<ITransform, ITransform>? OnChildrenRemoved { get; set; }
/// <summary>
/// The world position of the <see cref="ITransform"/> in 2D space.
/// </summary> /// </summary>
Vector2D Position { get; set; } Vector2D Position { get; set; }
/// <summary> /// <summary>
/// The scale of the <see cref="ITransform"/>. /// The world scale of the <see cref="ITransform"/>.
/// </summary> /// </summary>
Vector2D Scale { get; set; } Vector2D Scale { get; set; }
/// <summary> /// <summary>
/// The rotation of the <see cref="ITransform"/> in degrees. /// The world rotation of the <see cref="ITransform"/> in degrees.
/// </summary> /// </summary>
float Rotation { get; set; } float Rotation { get; set; }
/// <summary>
/// The local position of the <see cref="ITransform"/> in 2D space.
/// </summary>
Vector2D LocalPosition { get; set; }
/// <summary>
/// The local scale of the <see cref="ITransform"/>.
/// </summary>
Vector2D LocalScale { get; set; }
/// <summary>
/// The local rotation of the <see cref="ITransform"/> in degrees.
/// </summary>
float LocalRotation { get; set; }
/// <summary>
/// The parent <see cref="ITransform"/> of the <see cref="ITransform"/>.
/// </summary>
ITransform? Parent { get; }
/// <summary>
/// The <see cref="ITransform"/>s that have this <see cref="ITransform"/> as their <see cref="Parent"/>.
/// </summary>
IReadOnlyList<ITransform> Children { get; }
/// <summary>
/// Sets the parent <see cref="ITransform"/> of this <see cref="ITransform"/>.
/// </summary>
/// <param name="transform">The parent <see cref="ITransform"/> to set.</param>
void SetParent(ITransform? transform);
/// <summary>
/// Adds a child <see cref="ITransform"/> to this <see cref="ITransform"/>.
/// </summary>
/// <param name="transform">The child <see cref="ITransform"/> to add.</param>
void AddChild(ITransform transform);
/// <summary>
/// Removes a child <see cref="ITransform"/> from this <see cref="ITransform"/>.
/// </summary>
/// <param name="transform">The child <see cref="ITransform"/> to remove.</param>
void RemoveChild(ITransform transform);
} }

View File

@@ -6,13 +6,13 @@ using Syntriax.Engine.Core.Abstract;
namespace Syntriax.Engine.Core; namespace Syntriax.Engine.Core;
public class BehaviourCacher<T> : IAssignableGameManager, IEnumerable<T> public class BehaviourCollector<T> : IAssignableGameManager, IEnumerable<T>
{ {
public Action<IAssignable>? OnUnassigned { get; set; } = null; public Action<IAssignable>? OnUnassigned { get; set; } = null;
public Action<IAssignableGameManager>? OnGameManagerAssigned { get; set; } = null; public Action<IAssignableGameManager>? OnGameManagerAssigned { get; set; } = null;
public Action<BehaviourCacher<T>, T>? OnCached { get; set; } = null; public Action<BehaviourCollector<T>, T>? OnCollected { get; set; } = null;
public Action<BehaviourCacher<T>, T>? OnUncached { get; set; } = null; public Action<BehaviourCollector<T>, T>? OnRemoved { get; set; } = null;
private readonly List<T> _behaviours = new(32); private readonly List<T> _behaviours = new(32);
@@ -21,8 +21,8 @@ public class BehaviourCacher<T> : IAssignableGameManager, IEnumerable<T>
public T this[Index index] => _behaviours[index]; public T this[Index index] => _behaviours[index];
public BehaviourCacher() { } public BehaviourCollector() { }
public BehaviourCacher(IGameManager gameManager) => Assign(gameManager); public BehaviourCollector(IGameManager gameManager) => Assign(gameManager);
private void OnGameObjectRegistered(IGameManager manager, IGameObject gameObject) private void OnGameObjectRegistered(IGameManager manager, IGameObject gameObject)
{ {
@@ -42,7 +42,7 @@ public class BehaviourCacher<T> : IAssignableGameManager, IEnumerable<T>
return; return;
_behaviours.Add(tBehaviour); _behaviours.Add(tBehaviour);
OnCached?.Invoke(this, tBehaviour); OnCollected?.Invoke(this, tBehaviour);
} }
private void OnBehaviourRemoved(IBehaviourController controller, IBehaviour behaviour) private void OnBehaviourRemoved(IBehaviourController controller, IBehaviour behaviour)
@@ -53,7 +53,7 @@ public class BehaviourCacher<T> : IAssignableGameManager, IEnumerable<T>
if (!_behaviours.Remove(tBehaviour)) if (!_behaviours.Remove(tBehaviour))
return; return;
OnUncached?.Invoke(this, tBehaviour); OnRemoved?.Invoke(this, tBehaviour);
} }
public bool Assign(IGameManager gameManager) public bool Assign(IGameManager gameManager)

View File

@@ -0,0 +1,47 @@
using System.Diagnostics.CodeAnalysis;
using Syntriax.Engine.Core.Abstract;
namespace Syntriax.Engine.Core;
public static class BehaviourControllerExtensions
{
public static bool TryGetBehaviourInParent<T>(this IBehaviourController behaviourController, [NotNullWhen(returnValue: true)] out T? behaviour) where T : class
{
behaviour = GetBehaviourInParent<T>(behaviourController);
return behaviour is not null;
}
public static T? GetBehaviourInParent<T>(this IBehaviourController behaviourController) where T : class
{
IBehaviourController? controller = behaviourController;
while (controller is not null)
{
if (behaviourController.GetBehaviour<T>() is T behaviour)
return behaviour;
controller = controller.GameObject.Transform.Parent?.GameObject.BehaviourController;
}
return default;
}
public static bool TryGetBehaviourInChildren<T>(this IBehaviourController behaviourController, [NotNullWhen(returnValue: true)] out T? behaviour) where T : class
{
behaviour = GetBehaviourInChildren<T>(behaviourController);
return behaviour is not null;
}
public static T? GetBehaviourInChildren<T>(this IBehaviourController behaviourController) where T : class
{
if (behaviourController.GetBehaviour<T>() is T localBehaviour)
return localBehaviour;
foreach (ITransform transform in behaviourController.GameObject.Transform)
if (GetBehaviourInChildren<T>(transform.GameObject.BehaviourController) is T behaviour)
return behaviour;
return default;
}
}

View File

@@ -7,18 +7,22 @@ namespace Syntriax.Engine.Core;
public static class BehaviourExtensions public static class BehaviourExtensions
{ {
public static bool TryFindBehaviour<T>(this IEnumerable<IGameObject> gameObjects, [NotNullWhen(returnValue: true)] out T? behaviour) public static T? FindBehaviour<T>(this IEnumerable<IGameObject> gameObjects) where T : class
{ {
behaviour = default;
foreach (IGameObject gameObject in gameObjects) foreach (IGameObject gameObject in gameObjects)
if (gameObject.BehaviourController.TryGetBehaviour(out behaviour)) if (gameObject.BehaviourController.TryGetBehaviour(out T? behaviour))
return true; return behaviour;
return false; return default;
} }
public static void FindBehaviours<T>(this IEnumerable<IGameObject> gameObjects, List<T> behaviours) public static bool TryFindBehaviour<T>(this IEnumerable<IGameObject> gameObjects, [NotNullWhen(returnValue: true)] out T? behaviour) where T : class
{
behaviour = FindBehaviour<T>(gameObjects);
return behaviour is not null;
}
public static void FindBehaviours<T>(this IEnumerable<IGameObject> gameObjects, List<T> behaviours) where T : class
{ {
behaviours.Clear(); behaviours.Clear();
List<T> cache = []; List<T> cache = [];

View File

@@ -0,0 +1,9 @@
using Syntriax.Engine.Core.Abstract;
namespace Syntriax.Engine.Core;
public static class GameManagerExtensions
{
public static IGameObject InstantiateGameObject(this IGameManager gameManager, params object?[]? args)
=> gameManager.InstantiateGameObject<GameObject>(args);
}

View File

@@ -4,11 +4,16 @@ namespace Syntriax.Engine.Core;
public static class TransformExtensions public static class TransformExtensions
{ {
public static ITransform SetTransform(this ITransform transform, Vector2D? position = null, float? rotation = null, Vector2D? scale = null) public static ITransform SetTransform(this ITransform transform,
Vector2D? position = null, float? rotation = null, Vector2D? scale = null,
Vector2D? localPosition = null, float? localRotation = null, Vector2D? localScale = null)
{ {
if (position.HasValue) transform.Position = position.Value; if (position.HasValue) transform.Position = position.Value;
if (rotation.HasValue) transform.Rotation = rotation.Value; if (rotation.HasValue) transform.Rotation = rotation.Value;
if (scale.HasValue) transform.Scale = scale.Value; if (scale.HasValue) transform.Scale = scale.Value;
if (localPosition.HasValue) transform.LocalPosition = localPosition.Value;
if (localRotation.HasValue) transform.LocalRotation = localRotation.Value;
if (localScale.HasValue) transform.LocalScale = localScale.Value;
return transform; return transform;
} }
} }

View File

@@ -22,6 +22,9 @@ public class GameObjectFactory
behaviourController ??= TypeFactory.Get<BehaviourController>(); behaviourController ??= TypeFactory.Get<BehaviourController>();
stateEnable ??= TypeFactory.Get<StateEnable>(); stateEnable ??= TypeFactory.Get<StateEnable>();
if (!transform.Assign(gameObject))
throw AssignException.From(transform, gameObject);
if (!behaviourController.Assign(gameObject)) if (!behaviourController.Assign(gameObject))
throw AssignException.From(behaviourController, gameObject); throw AssignException.From(behaviourController, gameObject);
if (!stateEnable.Assign(gameObject)) if (!stateEnable.Assign(gameObject))

View File

@@ -1,20 +1,42 @@
using System; using System;
using System.Collections;
using System.Collections.Generic;
using Syntriax.Engine.Core.Abstract; using Syntriax.Engine.Core.Abstract;
namespace Syntriax.Engine.Core; namespace Syntriax.Engine.Core;
[System.Diagnostics.DebuggerDisplay("Position: {Position.ToString(), nq}, Scale: {Scale.ToString(), nq}, Rotation: {Rotation}")] [System.Diagnostics.DebuggerDisplay("Name: {GameObject.Name, nq} Position: {Position.ToString(), nq}, Scale: {Scale.ToString(), nq}, Rotation: {Rotation}")]
public class Transform : ITransform public class Transform : ITransform
{ {
public Action<IAssignableGameObject>? OnGameObjectAssigned { get; set; } = null;
public Action<IAssignable>? OnUnassigned { get; set; } = null;
public Action<ITransform>? OnPositionChanged { get; set; } = null; public Action<ITransform>? OnPositionChanged { get; set; } = null;
public Action<ITransform>? OnScaleChanged { get; set; } = null; public Action<ITransform>? OnScaleChanged { get; set; } = null;
public Action<ITransform>? OnRotationChanged { get; set; } = null; public Action<ITransform>? OnRotationChanged { get; set; } = null;
public Action<ITransform, ITransform?>? OnParentChanged { get; set; } = null;
public Action<ITransform, ITransform>? OnChildrenAdded { get; set; } = null;
public Action<ITransform, ITransform>? OnChildrenRemoved { get; set; } = null;
private Vector2D _position = Vector2D.Zero; private Vector2D _position = Vector2D.Zero;
private Vector2D _scale = Vector2D.One; private Vector2D _scale = Vector2D.One;
private float _rotation = 0f; private float _rotation = 0f;
private Vector2D _localPosition = Vector2D.Zero;
private Vector2D _localScale = Vector2D.One;
private float _localRotation = 0f;
private readonly List<ITransform> _children = [];
public IGameObject GameObject { get; private set; } = null!;
public ITransform? Parent { get; private set; } = null;
public IReadOnlyList<ITransform> Children => _children;
public Vector2D Position public Vector2D Position
{ {
get => _position; get => _position;
@@ -24,6 +46,7 @@ public class Transform : ITransform
return; return;
_position = value; _position = value;
UpdateLocalPosition();
OnPositionChanged?.Invoke(this); OnPositionChanged?.Invoke(this);
} }
} }
@@ -37,6 +60,7 @@ public class Transform : ITransform
return; return;
_scale = value; _scale = value;
UpdateLocalScale();
OnScaleChanged?.Invoke(this); OnScaleChanged?.Invoke(this);
} }
} }
@@ -50,7 +74,210 @@ public class Transform : ITransform
return; return;
_rotation = value; _rotation = value;
UpdateLocalPosition();
OnRotationChanged?.Invoke(this); OnRotationChanged?.Invoke(this);
} }
} }
public Vector2D LocalPosition
{
get => _localPosition;
set
{
if (value == _localPosition)
return;
_localPosition = value;
UpdatePosition();
OnPositionChanged?.Invoke(this);
}
}
public Vector2D LocalScale
{
get => _localScale;
set
{
if (value == _localScale)
return;
_localScale = value;
UpdateScale();
OnScaleChanged?.Invoke(this);
}
}
public float LocalRotation
{
get => _localRotation;
set
{
if (value == _localRotation)
return;
_localRotation = value;
UpdateRotation();
OnRotationChanged?.Invoke(this);
}
}
public void SetParent(ITransform? transform)
{
if (transform == this || Parent == transform)
return;
ITransform? previousParent = Parent;
if (previousParent is not null)
{
previousParent.RemoveChild(this);
previousParent.OnPositionChanged -= RecalculatePosition;
previousParent.OnScaleChanged -= RecalculateScale;
previousParent.OnRotationChanged -= RecalculateRotation;
previousParent.OnParentChanged -= NotifyChildrenOnParentChange;
}
Parent = transform;
if (transform is not null)
{
transform.AddChild(this);
transform.OnPositionChanged += RecalculatePosition;
transform.OnScaleChanged += RecalculateScale;
transform.OnRotationChanged += RecalculateRotation;
transform.OnParentChanged += NotifyChildrenOnParentChange;
}
UpdateLocalPosition();
UpdateLocalScale();
UpdateLocalRotation();
OnParentChanged?.Invoke(this, previousParent);
}
public void AddChild(ITransform transform)
{
if (_children.Contains(transform))
return;
_children.Add(transform);
transform.SetParent(this);
OnChildrenAdded?.Invoke(this, transform);
}
public void RemoveChild(ITransform transform)
{
if (!_children.Remove(transform))
return;
transform.SetParent(null);
OnChildrenRemoved?.Invoke(this, transform);
}
public IEnumerator<ITransform> GetEnumerator() => _children.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => _children.GetEnumerator();
private void NotifyChildrenOnParentChange(ITransform transform, ITransform? previousParent)
{
// TODO No idea how logical this is to propagate this to the children the way I'm doing right now.
// I was originally gonna just call `child.OnParentChanged?.Invoke(child, child.Parent);` but seems an unnecessary call too?
foreach (var child in Children)
child.OnParentChanged?.Invoke(transform, previousParent);
}
private void RecalculatePosition(ITransform _)
{
if (Parent is null)
return;
UpdatePosition();
OnPositionChanged?.Invoke(this);
}
private void RecalculateScale(ITransform _)
{
if (Parent is null)
return;
UpdateScale();
OnScaleChanged?.Invoke(this);
}
private void RecalculateRotation(ITransform _)
{
if (Parent is null)
return;
UpdatePosition();
UpdateRotation();
OnPositionChanged?.Invoke(this);
OnRotationChanged?.Invoke(this);
}
private void UpdateLocalPosition()
{
if (Parent is null)
_localPosition = Position;
else
_localPosition = Parent.Position.FromTo(Position).Scale(Parent.Scale);
}
private void UpdateLocalScale()
{
if (Parent is null)
_localScale = Scale;
else
_localScale = Scale.Scale(new(1f / Parent.Scale.X, 1f / Parent.Scale.Y));
}
private void UpdateLocalRotation()
{
if (Parent is null)
_localRotation = Rotation;
else
_localRotation = Rotation - Parent.Rotation;
}
private void UpdatePosition()
{
if (Parent is null)
_position = LocalPosition.Scale(Vector2D.One).Rotate(0f * Math.DegreeToRadian);
else
_position = Parent.Position + LocalPosition.Scale(new(1f / Parent.Scale.X, 1f / Parent.Scale.Y)).Rotate(Parent.Rotation * Math.DegreeToRadian);
}
private void UpdateScale()
{
if (Parent is null)
_scale = LocalScale;
else
_scale = Vector2D.Scale(Parent.Scale, LocalScale);
}
private void UpdateRotation()
{
if (Parent is null)
_rotation = LocalRotation;
else
_rotation = Parent.Rotation + LocalRotation;
}
public bool Assign(IGameObject gameObject)
{
if (GameObject is not null && GameObject.Initialized)
return false;
GameObject = gameObject;
OnGameObjectAssigned?.Invoke(this);
return true;
}
public bool Unassign()
{
if (GameObject is not null && GameObject.Initialized)
return false;
GameObject = null!;
OnUnassigned?.Invoke(this);
return true;
}
} }

View File

@@ -37,7 +37,7 @@ public abstract class Collider2DBehaviourBase : BehaviourOverride, ICollider2D
protected override void OnInitialize() protected override void OnInitialize()
{ {
BehaviourController.TryGetBehaviour(out _rigidBody2D); BehaviourController.TryGetBehaviourInParent(out _rigidBody2D);
BehaviourController.OnBehaviourAdded += OnBehaviourAddedToController; BehaviourController.OnBehaviourAdded += OnBehaviourAddedToController;
BehaviourController.OnBehaviourRemoved += OnBehaviourRemovedFromController; BehaviourController.OnBehaviourRemoved += OnBehaviourRemovedFromController;
@@ -45,6 +45,12 @@ public abstract class Collider2DBehaviourBase : BehaviourOverride, ICollider2D
Transform.OnPositionChanged += SetNeedsRecalculation; Transform.OnPositionChanged += SetNeedsRecalculation;
Transform.OnRotationChanged += SetNeedsRecalculation; Transform.OnRotationChanged += SetNeedsRecalculation;
Transform.OnScaleChanged += SetNeedsRecalculation; Transform.OnScaleChanged += SetNeedsRecalculation;
Transform.OnParentChanged += UpdateRigidBody2D;
}
private void UpdateRigidBody2D(ITransform _1, ITransform? _2)
{
BehaviourController.TryGetBehaviourInParent(out _rigidBody2D);
} }
private void OnBehaviourAddedToController(IBehaviourController _, IBehaviour behaviour) private void OnBehaviourAddedToController(IBehaviourController _, IBehaviour behaviour)

View File

@@ -1,13 +1,33 @@
using System;
using Syntriax.Engine.Core; using Syntriax.Engine.Core;
using Syntriax.Engine.Physics2D;
using Syntriax.Engine.Physics2D.Primitives; using Syntriax.Engine.Physics2D.Primitives;
namespace Engine.Physics2D; namespace Engine.Physics2D;
public static partial class Physics2D public static partial class Physics2D
{ {
public static bool Overlaps(this Shape shape, Vector2D point) => Overlaps(shape, point, out var _);
public static bool Overlaps(this Shape shape, Vector2D point, out float depth)
{
depth = float.MaxValue;
var vertices = shape.Vertices;
int count = vertices.Count;
for (int indexProjection = 0; indexProjection < count; indexProjection++)
{
Vector2D projectionVector = vertices[indexProjection].FromTo(vertices[(indexProjection + 1) % count]).Perpendicular().Normalized;
Projection shapeProjection = shape.ToProjection(projectionVector);
float projectedPoint = point.Dot(projectionVector);
if (shapeProjection.Max < projectedPoint || shapeProjection.Min > projectedPoint)
return false;
depth = Math.Min(depth, Math.Abs(Math.AbsMin(shapeProjection.Max - projectedPoint, shapeProjection.Min - projectedPoint)));
}
return true;
}
public static bool Overlaps(this Circle left, Circle right) public static bool Overlaps(this Circle left, Circle right)
{ {
float distanceSquared = left.Center.FromTo(right.Center).LengthSquared(); float distanceSquared = left.Center.FromTo(right.Center).LengthSquared();
@@ -27,7 +47,7 @@ public static partial class Physics2D
normal = distanceVector.Normalized; normal = distanceVector.Normalized;
if (isOverlapping) if (isOverlapping)
depth = MathF.Sqrt(radiusSumSquared - distanceSquared); depth = Math.Sqrt(radiusSumSquared - distanceSquared);
return isOverlapping; return isOverlapping;
} }
@@ -44,7 +64,7 @@ public static partial class Physics2D
normal = distanceVector.Normalized; normal = distanceVector.Normalized;
if (isOverlapping) if (isOverlapping)
depth = MathF.Sqrt(radiusSquared - distanceSquared); depth = Math.Sqrt(radiusSquared - distanceSquared);
return isOverlapping; return isOverlapping;
} }

View File

@@ -6,7 +6,7 @@ using Syntriax.Engine.Physics2D.Abstract;
namespace Syntriax.Engine.Physics2D; namespace Syntriax.Engine.Physics2D;
public class PhysicsEngine2DCacher : IPhysicsEngine2D, IAssignableGameManager public class PhysicsEngine2DCollector : IPhysicsEngine2D, IAssignableGameManager
{ {
public Action<IAssignable>? OnUnassigned { get; set; } = null; public Action<IAssignable>? OnUnassigned { get; set; } = null;
public Action<IAssignableGameManager>? OnGameManagerAssigned { get; set; } = null; public Action<IAssignableGameManager>? OnGameManagerAssigned { get; set; } = null;
@@ -17,8 +17,8 @@ public class PhysicsEngine2DCacher : IPhysicsEngine2D, IAssignableGameManager
protected readonly ICollisionDetector2D collisionDetector = null!; protected readonly ICollisionDetector2D collisionDetector = null!;
protected readonly ICollisionResolver2D collisionResolver = null!; protected readonly ICollisionResolver2D collisionResolver = null!;
protected BehaviourCacher<IRigidBody2D> rigidBodyCacher = new(); protected BehaviourCollector<IRigidBody2D> rigidBodyCollector = new();
protected BehaviourCacher<ICollider2D> colliderCacher = new(); protected BehaviourCollector<ICollider2D> colliderCollector = new();
public int IterationPerStep { get => _iterationPerStep; set => _iterationPerStep = value < 1 ? 1 : value; } public int IterationPerStep { get => _iterationPerStep; set => _iterationPerStep = value < 1 ? 1 : value; }
@@ -31,23 +31,23 @@ public class PhysicsEngine2DCacher : IPhysicsEngine2D, IAssignableGameManager
for (int iterationIndex = 0; iterationIndex < IterationPerStep; iterationIndex++) for (int iterationIndex = 0; iterationIndex < IterationPerStep; iterationIndex++)
{ {
// Can Parallel // Can Parallel
foreach (var rigidBody in rigidBodyCacher) foreach (var rigidBody in rigidBodyCollector)
StepRigidBody(rigidBody, intervalDeltaTime); StepRigidBody(rigidBody, intervalDeltaTime);
// Can Parallel // Can Parallel
foreach (var collider in colliderCacher) foreach (var collider in colliderCollector)
collider.Recalculate(); collider.Recalculate();
// Can Parallel // Can Parallel
for (int x = 0; x < colliderCacher.Behaviours.Count; x++) for (int x = 0; x < colliderCollector.Behaviours.Count; x++)
{ {
ICollider2D? colliderX = colliderCacher.Behaviours[x]; ICollider2D? colliderX = colliderCollector.Behaviours[x];
if (!colliderX.IsActive) if (!colliderX.IsActive)
return; return;
for (int y = x + 1; y < colliderCacher.Behaviours.Count; y++) for (int y = x + 1; y < colliderCollector.Behaviours.Count; y++)
{ {
ICollider2D? colliderY = colliderCacher.Behaviours[y]; ICollider2D? colliderY = colliderCollector.Behaviours[y];
if (!colliderY.IsActive) if (!colliderY.IsActive)
return; return;
@@ -100,8 +100,8 @@ public class PhysicsEngine2DCacher : IPhysicsEngine2D, IAssignableGameManager
if (GameManager is not null) if (GameManager is not null)
return false; return false;
colliderCacher.Assign(gameManager); colliderCollector.Assign(gameManager);
rigidBodyCacher.Assign(gameManager); rigidBodyCollector.Assign(gameManager);
GameManager = gameManager; GameManager = gameManager;
OnGameManagerAssigned?.Invoke(this); OnGameManagerAssigned?.Invoke(this);
@@ -114,35 +114,35 @@ public class PhysicsEngine2DCacher : IPhysicsEngine2D, IAssignableGameManager
if (GameManager is null) if (GameManager is null)
return false; return false;
colliderCacher.Unassign(); colliderCollector.Unassign();
rigidBodyCacher.Unassign(); rigidBodyCollector.Unassign();
GameManager = null!; GameManager = null!;
OnUnassigned?.Invoke(this); OnUnassigned?.Invoke(this);
return true; return true;
} }
public PhysicsEngine2DCacher() public PhysicsEngine2DCollector()
{ {
collisionDetector = new CollisionDetector2D(); collisionDetector = new CollisionDetector2D();
collisionResolver = new CollisionResolver2D(); collisionResolver = new CollisionResolver2D();
} }
public PhysicsEngine2DCacher(IGameManager gameManager) public PhysicsEngine2DCollector(IGameManager gameManager)
{ {
Assign(gameManager); Assign(gameManager);
collisionDetector = new CollisionDetector2D(); collisionDetector = new CollisionDetector2D();
collisionResolver = new CollisionResolver2D(); collisionResolver = new CollisionResolver2D();
} }
public PhysicsEngine2DCacher(IGameManager gameManager, ICollisionDetector2D collisionDetector, ICollisionResolver2D collisionResolver) public PhysicsEngine2DCollector(IGameManager gameManager, ICollisionDetector2D collisionDetector, ICollisionResolver2D collisionResolver)
{ {
Assign(gameManager); Assign(gameManager);
this.collisionDetector = collisionDetector; this.collisionDetector = collisionDetector;
this.collisionResolver = collisionResolver; this.collisionResolver = collisionResolver;
} }
public PhysicsEngine2DCacher(ICollisionDetector2D collisionDetector, ICollisionResolver2D collisionResolver) public PhysicsEngine2DCollector(ICollisionDetector2D collisionDetector, ICollisionResolver2D collisionResolver)
{ {
this.collisionDetector = collisionDetector; this.collisionDetector = collisionDetector;
this.collisionResolver = collisionResolver; this.collisionResolver = collisionResolver;

17
README.md Normal file
View File

@@ -0,0 +1,17 @@
# Work In Progress
This engine is still in development but the implemented features include:
- Modular Systems
- Behaviour System
- 2D Physics Engine(**Not Fully Completed, but usable**)
- Rigid Body Simulations
- Collision Detection (Convex Shape & Circle)
- Collision Resolution (**Not Fully Completed**)
- Vector2D, AABB, Circle, Line, LineEquation, Projection & Shape Data Types
- General Math
---
**A detailed README file will be written in the future. If you want to check out how to use this, please checkout this example Pong game made using this engine on top of [MonoGame](https://monogame.net/) from the link bellow.**
[Pong Source Code](https://git.syntriax.com/Syntriax/Engine-Pong)