Compare commits
	
		
			16 Commits
		
	
	
		
			e5732f0ac5
			...
			3428fcc6ca
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 3428fcc6ca | |||
| 528649659d | |||
| da67f4559b | |||
| 08b31d9db1 | |||
| 326bcfca61 | |||
| bfab35c27e | |||
| 468615e4cb | |||
| 56b46b93eb | |||
| 0c3bf48d2c | |||
| 77e1949f59 | |||
| fbf9bd5832 | |||
| d40183db65 | |||
| a60f79f12b | |||
| 4bf618251f | |||
| b3d404bb6b | |||
| 87bf47eefd | 
@@ -1,6 +1,7 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Diagnostics.CodeAnalysis;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
 | 
			
		||||
using Syntriax.Engine.Core.Abstract;
 | 
			
		||||
 | 
			
		||||
@@ -55,17 +56,17 @@ public class BehaviourController : IBehaviourController
 | 
			
		||||
 | 
			
		||||
    public IList<T> GetBehaviours<T>()
 | 
			
		||||
    {
 | 
			
		||||
        IList<T> behaviours = new List<T>();
 | 
			
		||||
        List<T>? behaviours = null;
 | 
			
		||||
        foreach (var behaviourItem in this.behaviours)
 | 
			
		||||
        {
 | 
			
		||||
            if (behaviourItem is not T behaviour)
 | 
			
		||||
                continue;
 | 
			
		||||
 | 
			
		||||
            behaviours ??= new List<T>();
 | 
			
		||||
            behaviours ??= [];
 | 
			
		||||
            behaviours.Add(behaviour);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return behaviours;
 | 
			
		||||
        return behaviours ?? Enumerable.Empty<T>().ToList();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void RemoveBehaviour<T>(bool removeAll = false) where T : class, IBehaviour
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										9
									
								
								Engine.Core/Extensions/Abstract/TransformExtensions.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								Engine.Core/Extensions/Abstract/TransformExtensions.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
namespace Syntriax.Engine.Core.Abstract;
 | 
			
		||||
 | 
			
		||||
public static class TransformExtensions
 | 
			
		||||
{
 | 
			
		||||
    public static Vector2D TransformVector2D(this ITransform transform, Vector2D vector)
 | 
			
		||||
        => vector.Scale(transform.Scale)
 | 
			
		||||
                 .Rotate(transform.Rotation * Math.DegreeToRadian)
 | 
			
		||||
                 .Add(transform.Position);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								Engine.Core/Extensions/FloatExtensions.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								Engine.Core/Extensions/FloatExtensions.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
namespace Syntriax.Engine.Core;
 | 
			
		||||
 | 
			
		||||
public static class FloatExtensions
 | 
			
		||||
{
 | 
			
		||||
    public static bool ApproximatelyEquals(this float a, float b)
 | 
			
		||||
        => ApproximatelyEquals(a, b, float.Epsilon);
 | 
			
		||||
    public static bool ApproximatelyEquals(this float a, float b, float epsilon)
 | 
			
		||||
    {
 | 
			
		||||
        if (a == b)
 | 
			
		||||
            return true;
 | 
			
		||||
 | 
			
		||||
        const float floatNormal = (1 << 23) * float.Epsilon;
 | 
			
		||||
        float absA = Math.Abs(a);
 | 
			
		||||
        float absB = Math.Abs(b);
 | 
			
		||||
        float diff = Math.Abs(a - b);
 | 
			
		||||
 | 
			
		||||
        if (a == 0.0f || b == 0.0f || diff < floatNormal)
 | 
			
		||||
            return diff < (epsilon * floatNormal);
 | 
			
		||||
 | 
			
		||||
        return diff / Math.Min(absA + absB, float.MaxValue) < epsilon;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -13,6 +13,7 @@ public static class Vector2DExtensions
 | 
			
		||||
    public static Vector2D Multiply(this Vector2D vector, float value) => Vector2D.Multiply(vector, value);
 | 
			
		||||
    public static Vector2D Subdivide(this Vector2D vector, float value) => Vector2D.Subdivide(vector, value);
 | 
			
		||||
 | 
			
		||||
    public static Vector2D Abs(this Vector2D vector) => Vector2D.Abs(vector);
 | 
			
		||||
    public static Vector2D Reflect(this Vector2D vector, Vector2D normal) => Vector2D.Reflect(vector, normal);
 | 
			
		||||
    public static Vector2D Normalize(this Vector2D vector) => Vector2D.Normalize(vector);
 | 
			
		||||
    public static Vector2D FromTo(this Vector2D from, Vector2D to) => Vector2D.FromTo(from, to);
 | 
			
		||||
@@ -27,4 +28,7 @@ public static class Vector2DExtensions
 | 
			
		||||
    public static float Cross(this Vector2D left, Vector2D right) => Vector2D.Cross(left, right);
 | 
			
		||||
    public static float AngleBetween(this Vector2D left, Vector2D right) => Vector2D.Angle(left, right);
 | 
			
		||||
    public static float Dot(this Vector2D left, Vector2D right) => Vector2D.Dot(left, right);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public static bool ApproximatelyEquals(this Vector2D left, Vector2D right, float epsilon = float.Epsilon) => Vector2D.ApproximatelyEquals(left, right, epsilon);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										32
									
								
								Engine.Core/Math.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								Engine.Core/Math.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
using System;
 | 
			
		||||
 | 
			
		||||
namespace Syntriax.Engine.Core;
 | 
			
		||||
 | 
			
		||||
public static class Math
 | 
			
		||||
{
 | 
			
		||||
    public const float RadianToDegree = 180f / PI;
 | 
			
		||||
    public const float DegreeToRadian = PI / 180f;
 | 
			
		||||
 | 
			
		||||
    public const float E = 2.718281828459045f;
 | 
			
		||||
    public const float PI = 3.1415926535897932f;
 | 
			
		||||
    public const float Tau = 2f * PI;
 | 
			
		||||
 | 
			
		||||
    public static float Abs(float x) => MathF.Abs(x);
 | 
			
		||||
    public static float Acos(float x) => MathF.Acos(x);
 | 
			
		||||
    public static float Asin(float x) => MathF.Asin(x);
 | 
			
		||||
    public static float Atan2(float y, float x) => MathF.Atan2(y, x);
 | 
			
		||||
    public static float Atanh(float x) => MathF.Atanh(x);
 | 
			
		||||
    public static float Clamp(float x, float min, float max) => (x < min) ? min : (x > max) ? max : x;
 | 
			
		||||
    public static float Ceiling(float x) => MathF.Ceiling(x);
 | 
			
		||||
    public static float CopySign(float x, float y) => MathF.CopySign(x, y);
 | 
			
		||||
    public static float Floor(float x) => MathF.Floor(x);
 | 
			
		||||
    public static float IEEERemainder(float x, float y) => MathF.IEEERemainder(x, y);
 | 
			
		||||
    public static float Log(float x, float y) => MathF.Log(x, y);
 | 
			
		||||
    public static float Max(float x, float y) => MathF.Max(x, y);
 | 
			
		||||
    public static float MaxMagnitude(float x, float y) => MathF.MaxMagnitude(x, y);
 | 
			
		||||
    public static float Min(float x, float y) => MathF.Min(x, y);
 | 
			
		||||
    public static float MinMagnitude(float x, float y) => MathF.MinMagnitude(x, y);
 | 
			
		||||
    public static float Pow(float x, float y) => MathF.Pow(x, y);
 | 
			
		||||
    public static float Round(float x, int digits, MidpointRounding mode) => MathF.Round(x, digits, mode);
 | 
			
		||||
    public static float Truncate(float x) => MathF.Truncate(x);
 | 
			
		||||
}
 | 
			
		||||
@@ -34,6 +34,7 @@ public record Vector2D(float X, float Y)
 | 
			
		||||
    public static Vector2D Multiply(Vector2D vector, float value) => vector * value;
 | 
			
		||||
    public static Vector2D Subdivide(Vector2D vector, float value) => vector / value;
 | 
			
		||||
 | 
			
		||||
    public static Vector2D Abs(Vector2D vector) => new(Math.Abs(vector.X), Math.Abs(vector.Y));
 | 
			
		||||
    public static Vector2D Normalize(Vector2D vector) => vector / Length(vector);
 | 
			
		||||
    public static Vector2D Reflect(Vector2D vector, Vector2D normal) => vector - 2f * Dot(vector, normal) * normal;
 | 
			
		||||
    public static Vector2D FromTo(Vector2D from, Vector2D to) => to - from;
 | 
			
		||||
@@ -49,5 +50,25 @@ public record Vector2D(float X, float Y)
 | 
			
		||||
    public static float Angle(Vector2D left, Vector2D right) => MathF.Acos(Dot(left, right) / (Length(left) * Length(right)));
 | 
			
		||||
    public static float Dot(Vector2D left, Vector2D right) => left.X * right.X + left.Y * right.Y;
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Finds the Orientation of 3 <see cref="Vector2D"/>s
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <returns>0 -> Collinear, 1 -> Clockwise, 2 -> Counterclockwise</returns>
 | 
			
		||||
    public static int Orientation(Vector2D left, Vector2D middle, Vector2D right)
 | 
			
		||||
    {
 | 
			
		||||
        Vector2D leftToMiddle = left.FromTo(middle);
 | 
			
		||||
        Vector2D middleToRight = middle.FromTo(right);
 | 
			
		||||
 | 
			
		||||
        float value = leftToMiddle.Y * middleToRight.X -
 | 
			
		||||
                    leftToMiddle.X * middleToRight.Y;
 | 
			
		||||
 | 
			
		||||
        if (value > 0) return 1;
 | 
			
		||||
        if (value < 0) return 2;
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static bool ApproximatelyEquals(Vector2D left, Vector2D right, float epsilon = float.Epsilon)
 | 
			
		||||
        => left.X.ApproximatelyEquals(right.X, epsilon) && left.Y.ApproximatelyEquals(right.Y, epsilon);
 | 
			
		||||
 | 
			
		||||
    public override string ToString() => $"{nameof(Vector2D)}({X}, {Y})";
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -8,9 +8,6 @@ namespace Engine.Physics2D;
 | 
			
		||||
 | 
			
		||||
public static partial class Physics2D
 | 
			
		||||
{
 | 
			
		||||
    public const float RadianToDegree = 57.29577866666166f;
 | 
			
		||||
    public const float DegreeToRadian = 0.01745329277777778f;
 | 
			
		||||
 | 
			
		||||
    public static bool Overlaps(this Circle left, Circle right)
 | 
			
		||||
    {
 | 
			
		||||
        float distanceSquared = left.Position.FromTo(right.Position).LengthSquared();
 | 
			
		||||
 
 | 
			
		||||
@@ -1,67 +0,0 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
 | 
			
		||||
using Syntriax.Engine.Core;
 | 
			
		||||
using Syntriax.Engine.Physics2D.Primitives;
 | 
			
		||||
 | 
			
		||||
namespace Syntriax.Engine.Physics2D;
 | 
			
		||||
 | 
			
		||||
public static class PhysicsMath
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // Given three collinear points p, q, r, the function checks if 
 | 
			
		||||
    // point q lies on line segment 'pr' 
 | 
			
		||||
    public static bool OnSegment(Vector2D p, Vector2D q, Vector2D r)
 | 
			
		||||
    {
 | 
			
		||||
        if (q.X <= MathF.Max(p.X, r.X) && q.X >= MathF.Min(p.X, r.X) &&
 | 
			
		||||
            q.Y <= MathF.Max(p.Y, r.Y) && q.Y >= MathF.Min(p.Y, r.Y))
 | 
			
		||||
            return true;
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // To find orientation of ordered triplet (p, q, r). 
 | 
			
		||||
    // The function returns following values 
 | 
			
		||||
    // 0 --> p, q and r are collinear 
 | 
			
		||||
    // 1 --> Clockwise 
 | 
			
		||||
    // 2 --> Counterclockwise 
 | 
			
		||||
    public static int Orientation(Vector2D p, Vector2D q, Vector2D r)
 | 
			
		||||
    {
 | 
			
		||||
        // See https://www.geeksforgeeks.org/orientation-3-ordered-points/ 
 | 
			
		||||
        // for details of below formula. 
 | 
			
		||||
        float val = (q.Y - p.Y) * (r.X - q.X) -
 | 
			
		||||
                (q.X - p.X) * (r.Y - q.Y);
 | 
			
		||||
 | 
			
		||||
        if (val == 0) return 0; // collinear 
 | 
			
		||||
 | 
			
		||||
        return (val > 0) ? 1 : 2; // clock or counterclock wise 
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static float IntersectionParameterT(Vector2D p0, Vector2D p1, Vector2D q0, Vector2D q1)
 | 
			
		||||
        => ((q0.X - p0.X) * (p1.Y - p0.Y) - (q0.Y - p0.Y) * (p1.X - p0.X)) /
 | 
			
		||||
            ((q1.Y - q0.Y) * (p1.X - p0.X) - (q1.X - q0.X) * (p1.Y - p0.Y));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public static bool ApproximatelyEquals(this float a, float b)
 | 
			
		||||
        => ApproximatelyEquals(a, b, float.Epsilon);
 | 
			
		||||
    public static bool ApproximatelyEquals(this Vector2D a, Vector2D b)
 | 
			
		||||
        => ApproximatelyEquals(a, b, float.Epsilon);
 | 
			
		||||
    public static bool ApproximatelyEquals(this Vector2D a, Vector2D b, float epsilon)
 | 
			
		||||
        => ApproximatelyEquals(a.X, b.X, epsilon) && ApproximatelyEquals(a.Y, b.Y, epsilon);
 | 
			
		||||
    public static bool ApproximatelyEquals(this float a, float b, float epsilon)
 | 
			
		||||
    {
 | 
			
		||||
        if (a == b)
 | 
			
		||||
            return true;
 | 
			
		||||
 | 
			
		||||
        const float floatNormal = (1 << 23) * float.Epsilon;
 | 
			
		||||
        float absA = MathF.Abs(a);
 | 
			
		||||
        float absB = MathF.Abs(b);
 | 
			
		||||
        float diff = MathF.Abs(a - b);
 | 
			
		||||
 | 
			
		||||
        if (a == 0.0f || b == 0.0f || diff < floatNormal)
 | 
			
		||||
            return diff < (epsilon * floatNormal);
 | 
			
		||||
 | 
			
		||||
        return diff / MathF.Min(absA + absB, float.MaxValue) < epsilon;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,14 +1,42 @@
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
 | 
			
		||||
using Syntriax.Engine.Core;
 | 
			
		||||
 | 
			
		||||
namespace Syntriax.Engine.Physics2D.Primitives;
 | 
			
		||||
 | 
			
		||||
public record AABB(Vector2D LowerBoundary, Vector2D UpperBoundary)
 | 
			
		||||
{
 | 
			
		||||
    public Vector2D Center => (LowerBoundary + UpperBoundary) * .5f;
 | 
			
		||||
    public Vector2D Size => LowerBoundary.FromTo(UpperBoundary).Abs();
 | 
			
		||||
    public Vector2D SizeHalf => Size * .5f;
 | 
			
		||||
 | 
			
		||||
    public static AABB FromVectors(IEnumerable<Vector2D> vectors)
 | 
			
		||||
    {
 | 
			
		||||
        int counter = 0;
 | 
			
		||||
 | 
			
		||||
        Vector2D lowerBoundary = new(float.MaxValue, float.MaxValue);
 | 
			
		||||
        Vector2D upperBoundary = new(float.MinValue, float.MinValue);
 | 
			
		||||
 | 
			
		||||
        foreach (Vector2D vector in vectors)
 | 
			
		||||
        {
 | 
			
		||||
            lowerBoundary = Vector2D.Min(lowerBoundary, vector);
 | 
			
		||||
            upperBoundary = Vector2D.Max(upperBoundary, vector);
 | 
			
		||||
            counter++;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (counter < 2)
 | 
			
		||||
            throw new System.ArgumentException($"Parameter {nameof(vectors)} must have at least 2 items.");
 | 
			
		||||
 | 
			
		||||
        return new(lowerBoundary, upperBoundary);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static bool ApproximatelyEquals(AABB left, AABB right)
 | 
			
		||||
        => left.LowerBoundary.ApproximatelyEquals(right.LowerBoundary) && left.UpperBoundary.ApproximatelyEquals(right.UpperBoundary);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
public static class AABBExtensions
 | 
			
		||||
{
 | 
			
		||||
    public static AABB ToAABB(this IEnumerable<Vector2D> vectors) => AABB.FromVectors(vectors);
 | 
			
		||||
 | 
			
		||||
    public static bool ApproximatelyEquals(this AABB left, AABB right) => AABB.ApproximatelyEquals(left, right);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -107,18 +107,27 @@ public record Line(Vector2D From, Vector2D To)
 | 
			
		||||
 | 
			
		||||
    public static bool Intersects(Line left, Line right)
 | 
			
		||||
    {
 | 
			
		||||
        int o1 = PhysicsMath.Orientation(left.From, left.To, right.From);
 | 
			
		||||
        int o2 = PhysicsMath.Orientation(left.From, left.To, right.To);
 | 
			
		||||
        int o3 = PhysicsMath.Orientation(right.From, right.To, left.From);
 | 
			
		||||
        int o4 = PhysicsMath.Orientation(right.From, right.To, left.To);
 | 
			
		||||
        int o1 = Vector2D.Orientation(left.From, left.To, right.From);
 | 
			
		||||
        int o2 = Vector2D.Orientation(left.From, left.To, right.To);
 | 
			
		||||
        int o3 = Vector2D.Orientation(right.From, right.To, left.From);
 | 
			
		||||
        int o4 = Vector2D.Orientation(right.From, right.To, left.To);
 | 
			
		||||
 | 
			
		||||
        if (o1 != o2 && o3 != o4)
 | 
			
		||||
            return true;
 | 
			
		||||
 | 
			
		||||
        if (o1 == 0 && PhysicsMath.OnSegment(left.From, right.From, left.To)) return true;
 | 
			
		||||
        if (o2 == 0 && PhysicsMath.OnSegment(left.From, right.To, left.To)) return true;
 | 
			
		||||
        if (o3 == 0 && PhysicsMath.OnSegment(right.From, left.From, right.To)) return true;
 | 
			
		||||
        if (o4 == 0 && PhysicsMath.OnSegment(right.From, left.To, right.To)) return true;
 | 
			
		||||
        if (o1 == 0 && OnSegment(left, right.From)) return true;
 | 
			
		||||
        if (o2 == 0 && OnSegment(left, right.To)) return true;
 | 
			
		||||
        if (o3 == 0 && OnSegment(right, left.From)) return true;
 | 
			
		||||
        if (o4 == 0 && OnSegment(right, left.To)) return true;
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static bool OnSegment(Line line, Vector2D point)
 | 
			
		||||
    {
 | 
			
		||||
        if (point.X <= MathF.Max(line.From.X, line.To.X) && point.X >= MathF.Min(line.From.X, line.To.X) &&
 | 
			
		||||
            point.Y <= MathF.Max(line.From.Y, line.To.Y) && point.Y >= MathF.Min(line.From.Y, line.To.Y))
 | 
			
		||||
            return true;
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,5 @@
 | 
			
		||||
using Syntriax.Engine.Core;
 | 
			
		||||
 | 
			
		||||
namespace Syntriax.Engine.Physics2D.Primitives;
 | 
			
		||||
 | 
			
		||||
public record LineEquation(float Slope, float OffsetY)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,12 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
 | 
			
		||||
using Syntriax.Engine.Core;
 | 
			
		||||
 | 
			
		||||
namespace Syntriax.Engine.Physics2D.Primitives;
 | 
			
		||||
 | 
			
		||||
public record Shape(IList<Vector2D> Vertices)
 | 
			
		||||
public record Shape(IList<Vector2D> Vertices) : IEnumerable<Vector2D>
 | 
			
		||||
{
 | 
			
		||||
    public Vector2D this[Index index] => Vertices[index];
 | 
			
		||||
 | 
			
		||||
@@ -61,6 +62,9 @@ public record Shape(IList<Vector2D> Vertices)
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public IEnumerator<Vector2D> GetEnumerator() => Vertices.GetEnumerator();
 | 
			
		||||
    IEnumerator IEnumerable.GetEnumerator() => Vertices.GetEnumerator();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
public static class ShapeExtensions
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user