Engine DeMonoGame #2

This commit is contained in:
Syntriax 2024-01-23 12:16:58 +03:00
parent 0486b0343a
commit ba284a199a
17 changed files with 135 additions and 124 deletions

2
Engine

@ -1 +1 @@
Subproject commit 485dfcc51ea548a50eec57b003bc3cb31cfdf579
Subproject commit 39e553ebbf61f398a3ed9a96b20f6819a197cd86

View File

@ -6,12 +6,12 @@ using Syntriax.Engine.Input;
using Syntriax.Engine.Physics2D.Abstract;
namespace Pong.Behaviours;
public class MovementBallBehaviour(Vector2 StartDirection, float Speed) : BehaviourOverride
public class MovementBallBehaviour(Vector2D StartDirection, float Speed) : BehaviourOverride
{
public Vector2 StartDirection { get; private set; } = Vector2.Normalize(StartDirection);
public Vector2D StartDirection { get; private set; } = Vector2D.Normalize(StartDirection);
public float Speed { get; set; } = Speed;
protected override void OnFirstActiveFrame(GameTime time)
protected override void OnFirstActiveFrame()
{
if (!BehaviourController.TryGetBehaviour(out IRigidBody2D? rigidBody))
throw new Exception($"Where's my {nameof(IRigidBody2D)}????");

View File

@ -17,25 +17,25 @@ public class MovementBoxBehaviour(Keys Up, Keys Down, float High, float Low, flo
private bool isUpPressed = false;
private bool isDownPressed = false;
private IKeyboardInputs inputs = null!;
private IButtonInputs<Keys> inputs = null!;
protected override void OnUpdate(GameTime time)
protected override void OnUpdate()
{
if (isUpPressed && isDownPressed)
return;
if (isUpPressed)
GameObject.Transform.Position = GameObject.Transform.Position + Vector2.UnitY * (float)time.ElapsedGameTime.TotalSeconds * Speed;
GameObject.Transform.Position = GameObject.Transform.Position + Vector2D.Up * (float)Time.Elapsed.TotalSeconds * Speed;
else if (isDownPressed)
GameObject.Transform.Position = GameObject.Transform.Position + -Vector2.UnitY * (float)time.ElapsedGameTime.TotalSeconds * Speed;
GameObject.Transform.Position = GameObject.Transform.Position + -Vector2D.Up * (float)Time.Elapsed.TotalSeconds * Speed;
GameObject.Transform.Position = new Vector2(GameObject.Transform.Position.X, MathF.Max(MathF.Min(GameObject.Transform.Position.Y, High), Low));
GameObject.Transform.Position = new Vector2D(GameObject.Transform.Position.X, MathF.Max(MathF.Min(GameObject.Transform.Position.Y, High), Low));
}
protected override void OnFirstActiveFrame(GameTime time)
protected override void OnFirstActiveFrame()
{
if (!BehaviourController.TryGetBehaviour<IKeyboardInputs>(out var behaviourResult))
throw new Exception($"{nameof(IKeyboardInputs)} is missing on ${GameObject.Name}.");
if (!BehaviourController.TryGetBehaviour<IButtonInputs<Keys>>(out var behaviourResult))
throw new Exception($"{nameof(IButtonInputs<Keys>)} is missing on ${GameObject.Name}.");
inputs = behaviourResult;
@ -55,8 +55,8 @@ public class MovementBoxBehaviour(Keys Up, Keys Down, float High, float Low, flo
inputs.UnregisterOnRelease(Down, OnDownReleased);
}
private void OnUpPressed(IKeyboardInputs inputs, Keys keys) => isUpPressed = true;
private void OnUpReleased(IKeyboardInputs inputs, Keys keys) => isUpPressed = false;
private void OnDownPressed(IKeyboardInputs inputs, Keys keys) => isDownPressed = true;
private void OnDownReleased(IKeyboardInputs inputs, Keys keys) => isDownPressed = false;
private void OnUpPressed(IButtonInputs<Keys> inputs, Keys keys) => isUpPressed = true;
private void OnUpReleased(IButtonInputs<Keys> inputs, Keys keys) => isUpPressed = false;
private void OnDownPressed(IButtonInputs<Keys> inputs, Keys keys) => isDownPressed = true;
private void OnDownReleased(IButtonInputs<Keys> inputs, Keys keys) => isDownPressed = false;
}

11
Game/EngineConverted.cs Normal file
View File

@ -0,0 +1,11 @@
using System.Runtime.CompilerServices;
using Microsoft.Xna.Framework;
using Syntriax.Engine.Core;
namespace Pong;
public static class EngineConverted
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static EngineTime ToEngineTime(this GameTime gameTime) => new(gameTime.TotalGameTime, gameTime.ElapsedGameTime);
}

View File

@ -26,7 +26,6 @@
<ItemGroup>
<ProjectReference Include="..\Engine\Engine.Core\Engine.Core.csproj" />
<ProjectReference Include="..\Engine\Engine.Input\Engine.Input.csproj" />
<ProjectReference Include="..\Engine\Engine.Graphics\Engine.Graphics.csproj" />
</ItemGroup>
<Target Name="RestoreDotnetTools" BeforeTargets="Restore">
<Message Text="Restoring dotnet tools" Importance="High" />

View File

@ -1,5 +1,4 @@
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
@ -19,7 +18,9 @@ public class Game1 : Game
private PhysicsEngine2D engine;
private SpriteBatch _spriteBatch = null!;
public static GameManager gameManager = null!;
public static Sprite spriteBox = null!;
// public static Sprite spriteBox = null!;
private MonoGameCameraBehaviour cameraBehaviour;
public Game1()
{
@ -49,16 +50,16 @@ public class Game1 : Game
{
_spriteBatch = new SpriteBatch(GraphicsDevice);
spriteBox = new Sprite() { Texture2D = Content.Load<Texture2D>("Sprites/Pixel") };
Sprite spriteBall = new Sprite() { Texture2D = Content.Load<Texture2D>("Sprites/Circle") };
// spriteBox = new Sprite() { Texture2D = Content.Load<Texture2D>("Sprites/Pixel") };
// Sprite spriteBall = new Sprite() { Texture2D = Content.Load<Texture2D>("Sprites/Circle") };
IGameObject gameObjectCamera = gameManager.InstantiateGameObject<GameObject>();
gameObjectCamera.Name = "Camera";
gameObjectCamera.Transform.Position = Vector2D.Zero;
MonoGameCameraBehaviour monoGameCameraBehaviour = gameObjectCamera.BehaviourController.AddBehaviour<MonoGameCameraBehaviour>();
monoGameCameraBehaviour.Viewport = GraphicsDevice.Viewport;
gameManager.Camera = monoGameCameraBehaviour;
cameraBehaviour = gameObjectCamera.BehaviourController.AddBehaviour<MonoGameCameraBehaviour>();
cameraBehaviour.Viewport = GraphicsDevice.Viewport;
gameManager.Camera = cameraBehaviour;
GameObject gameObjectBall = gameManager.InstantiateGameObject<GameObject>();
gameObjectBall.Name = "Ball";
@ -67,7 +68,7 @@ public class Game1 : Game
engine.AddRigidBody(gameObjectBall.BehaviourController.AddBehaviour<RigidBody2D>());
gameObjectBall.BehaviourController.AddBehaviour<MovementBallBehaviour>(new Vector2D(.1f, .1f), 500f);
// gameObjectBall.BehaviourController.AddBehaviour<DisplayableSpriteBehaviour>().Assign(spriteBall);
gameObjectBall.BehaviourController.AddBehaviour<Collider2DAABBBehaviour>().AABBLocal = new AABB(-Vector2.One * 512f * .5f, Vector2.One * 512f * .5f);
gameObjectBall.BehaviourController.AddBehaviour<Collider2DAABBBehaviour>().AABBLocal = new AABB(-Vector2D.One * 512f * .5f, Vector2D.One * 512f * .5f);
// gameObjectBall = gameManager.InstantiateGameObject<GameObject>();
// gameObjectBall.Name = "Ball";
// gameObjectBall.Transform.Position = Vector2D.UnitY * 30f;
@ -102,26 +103,26 @@ public class Game1 : Game
goPlayAreaTop.Transform.Position = new Vector2D(0f, 288f + 20f);
goPlayAreaTop.Transform.Scale = new Vector2D(10240f, 40f);
// goPlayAreaTop.BehaviourController.AddBehaviour<DisplayableSpriteBehaviour>().Assign(spriteBox);
goPlayAreaTop.BehaviourController.AddBehaviour<Collider2DAABBBehaviour>().AABBLocal = new AABB(-Vector2D.One * .5f, Vector2D.One * .5f);
// goPlayAreaTop.BehaviourController.AddBehaviour<Collider2DAABBBehaviour>().AABBLocal = new AABB(-Vector2D.One * .5f, Vector2D.One * .5f);
engine.AddRigidBody(goPlayAreaTop.BehaviourController.AddBehaviour<RigidBody2D>());
IGameObject goPlayAreaBottom = gameManager.InstantiateGameObject<GameObject>();
goPlayAreaBottom.Transform.Position = new Vector2D(0f, -(288f + 20f));
goPlayAreaBottom.Transform.Scale = new Vector2D(10240f, 40f);
// goPlayAreaBottom.BehaviourController.AddBehaviour<DisplayableSpriteBehaviour>().Assign(spriteBox);
goPlayAreaBottom.BehaviourController.AddBehaviour<Collider2DAABBBehaviour>().AABBLocal = new AABB(-Vector2D.One * .5f, Vector2D.One * .5f);
// goPlayAreaBottom.BehaviourController.AddBehaviour<Collider2DAABBBehaviour>().AABBLocal = new AABB(-Vector2D.One * .5f, Vector2D.One * .5f);
engine.AddRigidBody(goPlayAreaBottom.BehaviourController.AddBehaviour<RigidBody2D>());
IGameObject goPlayAreaRight = gameManager.InstantiateGameObject<GameObject>();
goPlayAreaRight.Transform.Position = new Vector2D(512f + 20f, 0f);
goPlayAreaRight.Transform.Scale = new Vector2D(40f, 5760f);
// goPlayAreaRight.BehaviourController.AddBehaviour<DisplayableSpriteBehaviour>().Assign(spriteBox);
goPlayAreaRight.BehaviourController.AddBehaviour<Collider2DAABBBehaviour>().AABBLocal = new AABB(-Vector2D.One * .5f, Vector2D.One * .5f);
// goPlayAreaRight.BehaviourController.AddBehaviour<Collider2DAABBBehaviour>().AABBLocal = new AABB(-Vector2D.One * .5f, Vector2D.One * .5f);
engine.AddRigidBody(goPlayAreaRight.BehaviourController.AddBehaviour<RigidBody2D>());
IGameObject goPlayAreaLeft = gameManager.InstantiateGameObject<GameObject>();
goPlayAreaLeft.Transform.Position = new Vector2D(-(512f + 20f), 0f);
goPlayAreaLeft.Transform.Scale = new Vector2D(40f, 5760f);
// goPlayAreaLeft.BehaviourController.AddBehaviour<DisplayableSpriteBehaviour>().Assign(spriteBox);
goPlayAreaLeft.BehaviourController.AddBehaviour<Collider2DAABBBehaviour>().AABBLocal = new AABB(-Vector2D.One * .5f, Vector2D.One * .5f);
// goPlayAreaLeft.BehaviourController.AddBehaviour<Collider2DAABBBehaviour>().AABBLocal = new AABB(-Vector2D.One * .5f, Vector2D.One * .5f);
engine.AddRigidBody(goPlayAreaLeft.BehaviourController.AddBehaviour<RigidBody2D>());
// IGameObject goPlayAreaCenter = gameManager.InstantiateGameObject<GameObject>();
@ -132,7 +133,7 @@ public class Game1 : Game
// TODO: use this.Content to load your game content here
}
protected override void Update(Microsoft.Xna.Framework.GameTime gameTime)
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
@ -148,21 +149,21 @@ public class Game1 : Game
_graphics.IsFullScreen = true;
_graphics.ApplyChanges();
float previousScreenSize = MathF.Sqrt(MathF.Pow(gameManager.Camera.Viewport.Width, 2f) + MathF.Pow(gameManager.Camera.Viewport.Height, 2f));
float previousScreenSize = MathF.Sqrt(MathF.Pow(cameraBehaviour.Viewport.Width, 2f) + MathF.Pow(cameraBehaviour.Viewport.Height, 2f));
float currentScreenSize = MathF.Sqrt(MathF.Pow(GraphicsDevice.Viewport.Width, 2f) + MathF.Pow(GraphicsDevice.Viewport.Height, 2f));
gameManager.Camera.Zoom /= previousScreenSize / currentScreenSize;
gameManager.Camera.Viewport = GraphicsDevice.Viewport;
cameraBehaviour.Zoom /= previousScreenSize / currentScreenSize;
cameraBehaviour.Viewport = GraphicsDevice.Viewport;
}
if (Keyboard.GetState().IsKeyDown(Keys.U))
gameManager.Camera.Zoom += gameTime.ElapsedGameTime.Nanoseconds * 0.00025f;
cameraBehaviour.Zoom += gameTime.ElapsedGameTime.Nanoseconds * 0.00025f;
if (Keyboard.GetState().IsKeyDown(Keys.J))
gameManager.Camera.Zoom -= gameTime.ElapsedGameTime.Nanoseconds * 0.00025f;
cameraBehaviour.Zoom -= gameTime.ElapsedGameTime.Nanoseconds * 0.00025f;
if (Keyboard.GetState().IsKeyDown(Keys.Q))
gameManager.Camera.Transform.Rotation += gameTime.ElapsedGameTime.Nanoseconds * 0.000025f;
cameraBehaviour.BehaviourController.GameObject.Transform.Rotation += gameTime.ElapsedGameTime.Nanoseconds * 0.000025f;
if (Keyboard.GetState().IsKeyDown(Keys.E))
gameManager.Camera.Transform.Rotation -= gameTime.ElapsedGameTime.Nanoseconds * 0.000025f;
cameraBehaviour.BehaviourController.GameObject.Transform.Rotation -= gameTime.ElapsedGameTime.Nanoseconds * 0.000025f;
if (Keyboard.GetState().IsKeyDown(Keys.N))
{
@ -210,7 +211,7 @@ public class Game1 : Game
// physicsTimer += 0.01f;
// engine.Step(.01f);
// }
gameManager.Update(gameTime);
gameManager.Update(gameTime.ToEngineTime());
base.Update(gameTime);
}
static float physicsTimer = 0f;
@ -224,9 +225,9 @@ public class Game1 : Game
// Console.WriteLine($"Pos: {gameManager.Camera.Position}");
// TODO: Add your drawing code here
gameManager.PreDraw(gameTime);
gameManager.PreDraw();
gameManager.Camera.Update();
gameManager.Draw(_spriteBatch);
// gameManager.Draw(_spriteBatch);
base.Draw(gameTime);
}

View File

@ -1,8 +1,7 @@
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Syntriax.Engine.Core;
using Syntriax.Engine.Core.Abstract;
namespace Syntriax.Engine.Physics2D.Abstract;
@ -13,8 +12,8 @@ public interface ICollider2D : IBehaviour, IAssignableTransform
IRigidBody2D? RigidBody2D { get; }
IList<Vector2> Vertices { get; }
IList<Vector2D> Vertices { get; }
bool CheckCollision(Vector2 point);
bool CheckCollision(Vector2D point);
void Recalculate();
}

View File

@ -1,5 +1,4 @@
using Microsoft.Xna.Framework;
using Syntriax.Engine.Core;
using Syntriax.Engine.Core.Abstract;
namespace Syntriax.Engine.Physics2D.Abstract;
@ -8,7 +7,7 @@ public interface IRigidBody2D : IBehaviour, IAssignableTransform
{
IPhysicsMaterial2D Material { get; set; }
Vector2 Velocity { get; set; }
Vector2D Velocity { get; set; }
float AngularVelocity { get; set; }
float Mass { get; set; }

View File

@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Syntriax.Engine.Core;
using Syntriax.Engine.Core.Abstract;
using Syntriax.Engine.Physics2D.Abstract;
@ -16,7 +14,7 @@ public class Collider2DAABBBehaviour : BehaviourOverride, ICollider2D
public AABB AABBWorld { get; private set; } = null!;
private IRigidBody2D? _rigidBody2D = null;
private List<Vector2> _vertices = new List<Vector2>(4);
private List<Vector2D> _vertices = new List<Vector2D>(4);
public IRigidBody2D? RigidBody2D
{
@ -35,9 +33,9 @@ public class Collider2DAABBBehaviour : BehaviourOverride, ICollider2D
ITransform IAssignableTransform.Transform => Transform;
public bool Assign(ITransform transform) => GameObject.Assign(transform);
public IList<Vector2> Vertices => _vertices;
public IList<Vector2D> Vertices => _vertices;
public bool CheckCollision(Vector2 point)
public bool CheckCollision(Vector2D point)
{
return AABBWorld.Overlaps(point);
}
@ -51,11 +49,11 @@ public class Collider2DAABBBehaviour : BehaviourOverride, ICollider2D
Vertices.Clear();
Vertices.Add(AABBWorld.LowerBoundary);
Vertices.Add(new Vector2(AABBWorld.LowerBoundary.X, AABBWorld.UpperBoundary.Y));
Vertices.Add(new Vector2D(AABBWorld.LowerBoundary.X, AABBWorld.UpperBoundary.Y));
Vertices.Add(AABBWorld.UpperBoundary);
Vertices.Add(new Vector2(AABBWorld.UpperBoundary.X, AABBWorld.LowerBoundary.Y));
Vertices.Add(new Vector2D(AABBWorld.UpperBoundary.X, AABBWorld.LowerBoundary.Y));
}
public Collider2DAABBBehaviour(Vector2 lowerBoundary, Vector2 upperBoundary)
public Collider2DAABBBehaviour(Vector2D lowerBoundary, Vector2D upperBoundary)
{
AABBLocal = new AABB(lowerBoundary, upperBoundary);
AABBWorld = new AABB(lowerBoundary, upperBoundary);
@ -63,7 +61,7 @@ public class Collider2DAABBBehaviour : BehaviourOverride, ICollider2D
public Collider2DAABBBehaviour()
{
AABBLocal = new(Vector2.Zero, Vector2.Zero);
AABBWorld = new(Vector2.Zero, Vector2.Zero);
AABBLocal = new(Vector2D.Zero, Vector2D.Zero);
AABBWorld = new(Vector2D.Zero, Vector2D.Zero);
}
}

View File

@ -2,7 +2,7 @@ using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Syntriax.Engine.Core;
using Syntriax.Engine.Core.Abstract;
using Syntriax.Engine.Physics2D.Abstract;
using Syntriax.Engine.Physics2D.Primitives;
@ -60,7 +60,7 @@ public class PhysicsEngine2D : IPhysicsEngine2D
}
}
private void ResolveCollision(ICollider2D c1, ICollider2D c2, Vector2 vertex, float intervalDeltaTime)
private void ResolveCollision(ICollider2D c1, ICollider2D c2, Vector2D vertex, float intervalDeltaTime)
{
if (c1.RigidBody2D is not IRigidBody2D)
return;
@ -71,16 +71,16 @@ public class PhysicsEngine2D : IPhysicsEngine2D
c2.Vertices.ToLines(lines);
Vector2 normal = Vector2.UnitY;
Vector2D normal = Vector2D.Up;
float t = 1f;
bool hasIntersectedWithLines = false;
foreach (var line in lines)
{
if (!vertexTrajectory.Intersects(line, out Vector2? intersectionPoint))
if (!vertexTrajectory.Intersects(line, out Vector2D? intersectionPoint))
continue;
if (intersectionPoint is not Vector2 ip)
if (intersectionPoint is not Vector2D ip)
continue;
float tTemp = vertexTrajectory.GetT(ip);
@ -88,7 +88,7 @@ public class PhysicsEngine2D : IPhysicsEngine2D
continue;
t = tTemp;
Vector2 lineDirection = line.Direction;
Vector2D lineDirection = line.Direction;
normal = new(lineDirection.Y, lineDirection.X);
hasIntersectedWithLines = true;
}
@ -99,11 +99,11 @@ public class PhysicsEngine2D : IPhysicsEngine2D
float rewindInterval = intervalDeltaTime - t * intervalDeltaTime;
StepRigidBody(c1.RigidBody2D, -rewindInterval);
c1.RigidBody2D.Velocity = Vector2.Reflect(c1.RigidBody2D.Velocity, normal);
c1.RigidBody2D.Velocity = Vector2D.Reflect(c1.RigidBody2D.Velocity, normal);
StepRigidBody(c1.RigidBody2D, rewindInterval);
}
private void CheckCollisions(ICollider2D collider2D, List<ICollider2D> collider2Ds, Action<ICollider2D, ICollider2D, Vector2> OnCollisionDetectedAction)
private void CheckCollisions(ICollider2D collider2D, List<ICollider2D> collider2Ds, Action<ICollider2D, ICollider2D, Vector2D> OnCollisionDetectedAction)
{
for (int i = 0; i < collider2Ds.Count; i++)
{
@ -113,7 +113,7 @@ public class PhysicsEngine2D : IPhysicsEngine2D
for (int y = 0; y < collider2D.Vertices.Count; y++)
{
Vector2 vertex = collider2D.Vertices[y];
Vector2D vertex = collider2D.Vertices[y];
if (collider2DItem.CheckCollision(vertex))
{
OnCollisionDetectedAction?.Invoke(collider2D, collider2DItem, vertex);
@ -128,7 +128,7 @@ public class PhysicsEngine2D : IPhysicsEngine2D
private void StepRigidBody(IRigidBody2D rigidBody, float intervalDeltaTime)
{
Vector2 nextPosition = rigidBody.Transform.Position;
Vector2D nextPosition = rigidBody.Transform.Position;
nextPosition += rigidBody.Velocity * intervalDeltaTime;
rigidBody.Transform.Position = nextPosition;

View File

@ -2,22 +2,22 @@ using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Syntriax.Engine.Core;
using Syntriax.Engine.Physics2D.Primitives;
namespace Syntriax.Engine.Physics2D;
public static class PhysicsMath
{
public static Vector2 Scale(this Vector2 original, Vector2 scale)
=> new Vector2(original.X * scale.X, original.Y * scale.Y);
public static Vector2D Scale(this Vector2D original, Vector2D scale)
=> new Vector2D(original.X * scale.X, original.Y * scale.Y);
public static Triangle ToSuperTriangle(this IList<Vector2> vertices)
public static Triangle ToSuperTriangle(this IList<Vector2D> vertices)
{
float minX = float.MaxValue, minY = float.MaxValue;
float maxX = float.MinValue, maxY = float.MinValue;
foreach (Vector2 point in vertices)
foreach (Vector2D point in vertices)
{
minX = MathF.Min(minX, point.X);
minY = MathF.Min(minY, point.Y);
@ -31,21 +31,21 @@ public static class PhysicsMath
float midX = (minX + maxX) / 2;
float midY = (minY + maxY) / 2;
Vector2 p1 = new Vector2((float)midX - 20f * (float)deltaMax, (float)midY - (float)deltaMax);
Vector2 p2 = new Vector2((float)midX, (float)midY + 20 * (float)deltaMax);
Vector2 p3 = new Vector2((float)midX + 20 * (float)deltaMax, (float)midY - (float)deltaMax);
Vector2D p1 = new Vector2D((float)midX - 20f * (float)deltaMax, (float)midY - (float)deltaMax);
Vector2D p2 = new Vector2D((float)midX, (float)midY + 20 * (float)deltaMax);
Vector2D p3 = new Vector2D((float)midX + 20 * (float)deltaMax, (float)midY - (float)deltaMax);
return new Triangle(p1, p2, p3);
}
public static IList<Line> ToLines(this IList<Vector2> vertices)
public static IList<Line> ToLines(this IList<Vector2D> vertices)
{
List<Line> lines = new List<Line>(vertices.Count - 1);
ToLines(vertices, lines);
return lines;
}
public static void ToLines(this IList<Vector2> vertices, IList<Line> lines)
public static void ToLines(this IList<Vector2D> vertices, IList<Line> lines)
{
lines.Clear();
for (int i = 0; i < vertices.Count - 1; i++)
@ -53,13 +53,13 @@ public static class PhysicsMath
lines.Add(new(vertices[^1], vertices[0]));
}
public static bool LaysOn(this Vector2 point, Line line)
public static bool LaysOn(this Vector2D point, Line line)
=> line.Resolve(point.X).ApproximatelyEquals(point);
// Given three collinear points p, q, r, the function checks if
// point q lies on line segment 'pr'
public static bool OnSegment(Vector2 p, Vector2 q, Vector2 r)
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))
@ -73,7 +73,7 @@ public static class PhysicsMath
// 0 --> p, q and r are collinear
// 1 --> Clockwise
// 2 --> Counterclockwise
public static int Orientation(Vector2 p, Vector2 q, Vector2 r)
public static int Orientation(Vector2D p, Vector2D q, Vector2D r)
{
// See https://www.geeksforgeeks.org/orientation-3-ordered-points/
// for details of below formula.
@ -85,7 +85,7 @@ public static class PhysicsMath
return (val > 0) ? 1 : 2; // clock or counterclock wise
}
public static float IntersectionParameterT(Vector2 p0, Vector2 p1, Vector2 q0, Vector2 q1)
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));
@ -96,6 +96,10 @@ public static class PhysicsMath
=> ApproximatelyEquals(a, b, float.Epsilon);
public static bool ApproximatelyEquals(this Vector2 a, Vector2 b, float epsilon)
=> ApproximatelyEquals(a.X, b.X, epsilon) && ApproximatelyEquals(a.Y, b.Y, 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)

View File

@ -1,10 +1,10 @@
using Microsoft.Xna.Framework;
using Syntriax.Engine.Core;
namespace Syntriax.Engine.Physics2D.Primitives;
public record AABB(Vector2 LowerBoundary, Vector2 UpperBoundary)
public record AABB(Vector2D LowerBoundary, Vector2D UpperBoundary)
{
public bool Overlaps(Vector2 point)
public bool Overlaps(Vector2D point)
=> point.X >= LowerBoundary.X && point.X <= UpperBoundary.X &&
point.Y >= LowerBoundary.Y && point.Y <= UpperBoundary.Y;

View File

@ -1,8 +1,8 @@
using Microsoft.Xna.Framework;
using Syntriax.Engine.Core;
namespace Syntriax.Engine.Physics2D.Primitives;
public record Circle(Vector2 Position, float Radius)
public record Circle(Vector2D Position, float Radius)
{
public bool Intersects(Circle other)
{
@ -12,7 +12,7 @@ public record Circle(Vector2 Position, float Radius)
return distanceSquared < radiusSumSquared;
}
public bool Overlaps(Vector2 point) => (Position - point).LengthSquared() <= Radius * Radius;
public bool Overlaps(Vector2D point) => (Position - point).LengthSquared() <= Radius * Radius;
public bool ApproximatelyEquals(Circle other)
=> Position.ApproximatelyEquals(other.Position) && Radius.ApproximatelyEquals(other.Radius);
}

View File

@ -2,14 +2,14 @@ using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Microsoft.Xna.Framework;
using Syntriax.Engine.Core;
namespace Syntriax.Engine.Physics2D.Primitives;
public record Line(Vector2 From, Vector2 To)
public record Line(Vector2D From, Vector2D To)
{
public Line Reversed => new(To, From);
public Vector2 Direction => Vector2.Normalize(To - From);
public Vector2D Direction => Vector2D.Normalize(To - From);
public float Length => (From - To).Length();
public float LengthSquared => (From - To).LengthSquared();
@ -17,7 +17,7 @@ public record Line(Vector2 From, Vector2 To)
{
get
{
Vector2 slopeVector = To - From;
Vector2D slopeVector = To - From;
float slope = slopeVector.Y / slopeVector.X;
float yOffset = From.Y - (slope * From.X);
@ -26,10 +26,10 @@ public record Line(Vector2 From, Vector2 To)
}
}
public bool Intersects(Vector2 point)
public bool Intersects(Vector2D point)
=> Resolve(point.X).ApproximatelyEquals(point);
public float GetT(Vector2 point)
public float GetT(Vector2D point)
{
float fromX = MathF.Abs(From.X);
float toX = MathF.Abs(To.X);
@ -51,18 +51,18 @@ public record Line(Vector2 From, Vector2 To)
return t;
}
public bool Exist(List<Vector2> vertices)
public bool Exist(List<Vector2D> vertices)
{
for (int i = 0; i < vertices.Count - 1; i++)
{
Vector2 vertexCurrent = vertices[i];
Vector2 vertexNext = vertices[i];
Vector2D vertexCurrent = vertices[i];
Vector2D vertexNext = vertices[i];
if (From == vertexCurrent && To == vertexNext) return true;
if (From == vertexNext && To == vertexCurrent) return true;
}
Vector2 vertexFirst = vertices[0];
Vector2 vertexLast = vertices[^1];
Vector2D vertexFirst = vertices[0];
Vector2D vertexLast = vertices[^1];
if (From == vertexFirst && To == vertexLast) return true;
if (From == vertexLast && To == vertexFirst) return true;
return false;
@ -80,20 +80,20 @@ public record Line(Vector2 From, Vector2 To)
return numerator / denominator;
}
public Vector2 Lerp(float t)
=> new Vector2(
public Vector2D Lerp(float t)
=> new Vector2D(
From.X + (To.X - From.X) * t,
From.Y + (To.Y - From.Y) * t
);
public Vector2 Resolve(float x)
=> new Vector2(x, LineEquation.Resolve(x));
public Vector2D Resolve(float x)
=> new Vector2D(x, LineEquation.Resolve(x));
public Vector2 ClosestPointTo(Vector2 point)
public Vector2D ClosestPointTo(Vector2D point)
{
// Convert edge points to vectors
var edgeVector = new Vector2(To.X - From.X, To.Y - From.Y);
var pointVector = new Vector2(point.X - From.X, point.Y - From.Y);
var edgeVector = new Vector2D(To.X - From.X, To.Y - From.Y);
var pointVector = new Vector2D(point.X - From.X, point.Y - From.Y);
// Calculate the projection of pointVector onto edgeVector
float t = (pointVector.X * edgeVector.X + pointVector.Y * edgeVector.Y) / (edgeVector.X * edgeVector.X + edgeVector.Y * edgeVector.Y);
@ -105,11 +105,11 @@ public record Line(Vector2 From, Vector2 To)
float closestX = From.X + t * edgeVector.X;
float closestY = From.Y + t * edgeVector.Y;
return new Vector2((float)closestX, (float)closestY);
return new Vector2D((float)closestX, (float)closestY);
}
public Vector2 IntersectionPoint(Line other)
=> Vector2.Lerp(From, To, IntersectionParameterT(other));
public Vector2D IntersectionPoint(Line other)
=> Vector2D.Lerp(From, To, IntersectionParameterT(other));
public bool Intersects(Line other)
{
@ -129,7 +129,7 @@ public record Line(Vector2 From, Vector2 To)
return false;
}
public bool Intersects(Line other, [NotNullWhen(returnValue: true)] out Vector2? point)
public bool Intersects(Line other, [NotNullWhen(returnValue: true)] out Vector2D? point)
{
point = null;

View File

@ -1,11 +1,11 @@
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Syntriax.Engine.Core;
namespace Syntriax.Engine.Physics2D.Primitives;
public record Shape(IList<Vector2> Vertices)
public record Shape(IList<Vector2D> Vertices)
{
public Triangle SuperTriangle
{
@ -14,7 +14,7 @@ public record Shape(IList<Vector2> Vertices)
float minX = float.MaxValue, minY = float.MaxValue;
float maxX = float.MinValue, maxY = float.MinValue;
foreach (Vector2 point in Vertices)
foreach (Vector2D point in Vertices)
{
minX = MathF.Min(minX, point.X);
minY = MathF.Min(minY, point.Y);
@ -28,9 +28,9 @@ public record Shape(IList<Vector2> Vertices)
float midX = (minX + maxX) / 2;
float midY = (minY + maxY) / 2;
Vector2 p1 = new Vector2((float)midX - 20f * (float)deltaMax, (float)midY - (float)deltaMax);
Vector2 p2 = new Vector2((float)midX, (float)midY + 20 * (float)deltaMax);
Vector2 p3 = new Vector2((float)midX + 20 * (float)deltaMax, (float)midY - (float)deltaMax);
Vector2D p1 = new Vector2D((float)midX - 20f * (float)deltaMax, (float)midY - (float)deltaMax);
Vector2D p2 = new Vector2D((float)midX, (float)midY + 20 * (float)deltaMax);
Vector2D p3 = new Vector2D((float)midX + 20 * (float)deltaMax, (float)midY - (float)deltaMax);
return new Triangle(p1, p2, p3);
}

View File

@ -1,10 +1,10 @@
using System;
using Microsoft.Xna.Framework;
using Syntriax.Engine.Core;
namespace Syntriax.Engine.Physics2D.Primitives;
public record Triangle(Vector2 A, Vector2 B, Vector2 C)
public record Triangle(Vector2D A, Vector2D B, Vector2D C)
{
public float Area => MathF.Abs((
A.X * (B.Y - C.Y) +
@ -16,27 +16,27 @@ public record Triangle(Vector2 A, Vector2 B, Vector2 C)
{
get
{
Vector2 midAB = (A + B) / 2;
Vector2 midBC = (B + C) / 2;
Vector2D midAB = (A + B) / 2;
Vector2D midBC = (B + C) / 2;
float slopeAB = (B.Y - A.Y) / (B.X - A.X);
float slopeBC = (C.Y - B.Y) / (C.X - B.X);
Vector2 center;
Vector2D center;
if (MathF.Abs(slopeAB - slopeBC) > float.Epsilon)
{
float x = (slopeAB * slopeBC * (A.Y - C.Y) + slopeBC * (A.X + B.X) - slopeAB * (B.X + C.X)) / (2 * (slopeBC - slopeAB));
float y = -(x - (A.X + B.X) / 2) / slopeAB + (A.Y + B.Y) / 2;
center = new Vector2(x, y);
center = new Vector2D(x, y);
}
else
center = (midAB + midBC) * .5f;
return new(center, Vector2.Distance(center, A));
return new(center, Vector2D.Distance(center, A));
}
}
public bool Overlaps(Vector2 point)
public bool Overlaps(Vector2D point)
{
float originalTriangleArea = Area;

View File

@ -15,7 +15,7 @@ public class RigidBody2D : BehaviourOverride, IRigidBody2D
public IPhysicsMaterial2D Material { get; set; } = null!;
public Vector2 Velocity { get; set; } = Vector2.Zero;
public Vector2D Velocity { get; set; } = Vector2D.Zero;
public float AngularVelocity { get; set; } = 0f;
public float Mass { get; set; } = 0f;
ITransform IAssignableTransform.Transform => Transform;