diff --git a/Engine b/Engine index c03d74d..485dfcc 160000 --- a/Engine +++ b/Engine @@ -1 +1 @@ -Subproject commit c03d74dbe0949d75411cd368c8b07dbafd871a20 +Subproject commit 485dfcc51ea548a50eec57b003bc3cb31cfdf579 diff --git a/Game/Behaviours/KeyboardInputsBehaviour.cs b/Game/Behaviours/KeyboardInputsBehaviour.cs new file mode 100644 index 0000000..46bf534 --- /dev/null +++ b/Game/Behaviours/KeyboardInputsBehaviour.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; + +using Microsoft.Xna.Framework.Input; + +using Syntriax.Engine.Core; +using Syntriax.Engine.Input; + +namespace Pong.Behaviours; + +public class KeyboardInputsBehaviour : BehaviourOverride, IButtonInputs +{ + private readonly Dictionary, Keys>> OnPressed = new(256); + private readonly Dictionary, Keys>> OnReleased = new(256); + + private int cachePressedCurrentlyCount = 0; + private readonly Keys[] cachePressedCurrently = new Keys[256]; + + private int cachePressedPreviouslyCount = 0; + private readonly Keys[] cachePressedPreviously = new Keys[256]; + + public void RegisterOnPress(Keys key, Action, Keys> callback) + { + if (OnPressed.TryGetValue(key, out var action)) + { + action += callback; + return; + } + + OnPressed.Add(key, callback); + } + + public void UnregisterOnPress(Keys key, Action, Keys> callback) + { + if (OnPressed.TryGetValue(key, out var action)) + action -= callback; + } + + public void RegisterOnRelease(Keys key, Action, Keys> callback) + { + if (OnReleased.TryGetValue(key, out var action)) + { + action += callback; + return; + } + + OnReleased.Add(key, callback); + } + + public void UnregisterOnRelease(Keys key, Action, Keys> callback) + { + if (OnReleased.TryGetValue(key, out var action)) + action -= callback; + } + + protected override void OnUpdate() + { + KeyboardState keyboardState = Keyboard.GetState(); + keyboardState.GetPressedKeys(cachePressedCurrently); + cachePressedCurrentlyCount = keyboardState.GetPressedKeyCount(); + + for (int i = 0; i < cachePressedCurrentlyCount; i++) + { + Keys currentlyPressedKey = cachePressedCurrently[i]; + + if (!OnPressed.TryGetValue(currentlyPressedKey, out var action)) + continue; + + if (WasPressed(currentlyPressedKey)) + continue; + + action.Invoke(this, currentlyPressedKey); + } + + for (int i = 0; i < cachePressedPreviouslyCount; i++) + { + Keys previouslyPressedKey = cachePressedPreviously[i]; + + if (!OnReleased.TryGetValue(previouslyPressedKey, out var action)) + continue; + + if (IsPressed(previouslyPressedKey)) + continue; + + action.Invoke(this, previouslyPressedKey); + } + + Array.Copy(cachePressedCurrently, cachePressedPreviously, cachePressedCurrentlyCount); + cachePressedPreviouslyCount = cachePressedCurrentlyCount; + } + + public bool IsPressed(Keys key) + { + for (int i = 0; i < cachePressedCurrentlyCount; i++) + if (cachePressedCurrently[i] == key) + return true; + return false; + } + + public bool WasPressed(Keys key) + { + for (int i = 0; i < cachePressedPreviouslyCount; i++) + if (cachePressedPreviously[i] == key) + return true; + return false; + } +} diff --git a/Game/Behaviours/MonoGameCameraBehaviour.cs b/Game/Behaviours/MonoGameCameraBehaviour.cs new file mode 100644 index 0000000..9cb088d --- /dev/null +++ b/Game/Behaviours/MonoGameCameraBehaviour.cs @@ -0,0 +1,106 @@ +using System; + +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +using Syntriax.Engine.Core; +using Syntriax.Engine.Core.Abstract; + +namespace Pong.Behaviours; + +public class MonoGameCameraBehaviour : BehaviourOverride, ICamera +{ + public Action? OnPositionChanged { get; set; } = null; + public Action? OnMatrixTransformChanged { get; set; } = null; + public Action? OnViewportChanged { get; set; } = null; + public Action? OnRotationChanged { get; set; } = null; + public Action? OnZoomChanged { get; set; } = null; + + private Matrix _matrixTransform = Matrix.Identity; + + private Viewport _viewport = default; + + private float _zoom = 1f; + + public Matrix MatrixTransform + { + get => _matrixTransform; + set + { + if (_matrixTransform == value) + return; + + _matrixTransform = value; + OnMatrixTransformChanged?.Invoke(this); + } + } + + public Vector2D Position + { + get => Transform.Position; + set => Transform.Position = value; + } + + public Viewport Viewport + { + get => _viewport; + set + { + if (_viewport.Equals(value)) + return; + + _viewport = value; + OnViewportChanged?.Invoke(this); + } + } + + public float Zoom + { + get => _zoom; + set + { + float newValue = value >= .1f ? value : .1f; + + if (_zoom == newValue) + return; + + _zoom = newValue; + OnZoomChanged?.Invoke(this); + } + } + + public float Rotation + { + get => Transform.Rotation; + set => Transform.Rotation = value; + } + public Action? OnTransformAssigned { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } + + ITransform IAssignableTransform.Transform => throw new NotImplementedException(); + + public void Update() + { + MatrixTransform = + Matrix.CreateTranslation(new Vector3(-Position.X, Position.Y, 0f)) * + Matrix.CreateRotationZ(Rotation) * + Matrix.CreateScale(Zoom) * + Matrix.CreateTranslation(new Vector3(_viewport.Width * .5f, _viewport.Height * .5f, 0f)); + } + + protected override void OnInitialize() + { + Transform.OnRotationChanged += OnTransformRotationChanged; + Transform.OnPositionChanged += OnTransformPositionChanged; + } + + protected override void OnFinalize() + { + Transform.OnRotationChanged -= OnTransformRotationChanged; + Transform.OnPositionChanged -= OnTransformPositionChanged; + } + + private void OnTransformRotationChanged(ITransform _) => OnRotationChanged?.Invoke(this); + private void OnTransformPositionChanged(ITransform _) => OnPositionChanged?.Invoke(this); + + public bool Assign(ITransform transform) => GameObject.Assign(transform); +} diff --git a/Game/Behaviours/MovementBallBehaviour.cs b/Game/Behaviours/MovementBallBehaviour.cs index d6c6b2a..ddfe614 100644 --- a/Game/Behaviours/MovementBallBehaviour.cs +++ b/Game/Behaviours/MovementBallBehaviour.cs @@ -6,7 +6,6 @@ using Syntriax.Engine.Input; using Syntriax.Engine.Physics2D.Abstract; namespace Pong.Behaviours; - public class MovementBallBehaviour(Vector2 StartDirection, float Speed) : BehaviourOverride { public Vector2 StartDirection { get; private set; } = Vector2.Normalize(StartDirection); diff --git a/Game/Game1.cs b/Game/Game1.cs index a1797ca..f8aff67 100644 --- a/Game/Game1.cs +++ b/Game/Game1.cs @@ -8,7 +8,6 @@ using Pong.Behaviours; using Syntriax.Engine.Core; using Syntriax.Engine.Core.Abstract; -using Syntriax.Engine.Graphics.TwoDimensional; using Syntriax.Engine.Physics2D; using Syntriax.Engine.Physics2D.Primitives; @@ -55,84 +54,85 @@ public class Game1 : Game IGameObject gameObjectCamera = gameManager.InstantiateGameObject(); gameObjectCamera.Name = "Camera"; - gameObjectCamera.Transform.Position = Vector2.Zero; + gameObjectCamera.Transform.Position = Vector2D.Zero; - gameManager.Camera = gameObjectCamera.BehaviourController.AddBehaviour(); - gameManager.Camera.Viewport = GraphicsDevice.Viewport; + MonoGameCameraBehaviour monoGameCameraBehaviour = gameObjectCamera.BehaviourController.AddBehaviour(); + monoGameCameraBehaviour.Viewport = GraphicsDevice.Viewport; + gameManager.Camera = monoGameCameraBehaviour; GameObject gameObjectBall = gameManager.InstantiateGameObject(); gameObjectBall.Name = "Ball"; - gameObjectBall.Transform.Position = Vector2.Zero; - gameObjectBall.Transform.Scale = new Vector2(1f / 51.2f, 1f / 51.2f); + gameObjectBall.Transform.Position = Vector2D.Zero; + gameObjectBall.Transform.Scale = new Vector2D(1f / 51.2f, 1f / 51.2f); engine.AddRigidBody(gameObjectBall.BehaviourController.AddBehaviour()); - gameObjectBall.BehaviourController.AddBehaviour(new Vector2(.1f, .1f), 500f); - gameObjectBall.BehaviourController.AddBehaviour().Assign(spriteBall); + gameObjectBall.BehaviourController.AddBehaviour(new Vector2D(.1f, .1f), 500f); + // gameObjectBall.BehaviourController.AddBehaviour().Assign(spriteBall); gameObjectBall.BehaviourController.AddBehaviour().AABBLocal = new AABB(-Vector2.One * 512f * .5f, Vector2.One * 512f * .5f); // gameObjectBall = gameManager.InstantiateGameObject(); // gameObjectBall.Name = "Ball"; - // gameObjectBall.Transform.Position = Vector2.UnitY * 30f; - // gameObjectBall.Transform.Scale = new Vector2(1f / 51.2f, 1f / 51.2f); + // gameObjectBall.Transform.Position = Vector2D.UnitY * 30f; + // gameObjectBall.Transform.Scale = new Vector2D(1f / 51.2f, 1f / 51.2f); // engine.AddRigidBody(gameObjectBall.BehaviourController.AddBehaviour()); - // gameObjectBall.BehaviourController.AddBehaviour(new Vector2(.1f, .01f), 500f); + // gameObjectBall.BehaviourController.AddBehaviour(new Vector2D(.1f, .01f), 500f); // gameObjectBall.BehaviourController.AddBehaviour().Assign(spriteBall); - // gameObjectBall.BehaviourController.AddBehaviour().AABBLocal = new AABB(-Vector2.One * 512f * .5f, Vector2.One * 512f * .5f); + // gameObjectBall.BehaviourController.AddBehaviour().AABBLocal = new AABB(-Vector2D.One * 512f * .5f, Vector2D.One * 512f * .5f); // IGameObject gameObjectLeft = gameManager.InstantiateGameObject(); // gameObjectLeft.Name = "Left"; - // gameObjectLeft.Transform.Position = new Vector2(-452, 0f); - // gameObjectLeft.Transform.Scale = new Vector2(10f, 40f); + // gameObjectLeft.Transform.Position = new Vector2D(-452, 0f); + // gameObjectLeft.Transform.Scale = new Vector2D(10f, 40f); // gameObjectLeft.BehaviourController.AddBehaviour(); // gameObjectLeft.BehaviourController.AddBehaviour(Keys.W, Keys.S, 268f, -268f, 400f); // gameObjectLeft.BehaviourController.AddBehaviour().Assign(spriteBox); - // gameObjectLeft.BehaviourController.AddBehaviour().AABBLocal = new AABB(-Vector2.One * .5f, Vector2.One * .5f); + // gameObjectLeft.BehaviourController.AddBehaviour().AABBLocal = new AABB(-Vector2D.One * .5f, Vector2D.One * .5f); // engine.AddRigidBody(gameObjectLeft.BehaviourController.AddBehaviour()); // IGameObject gameObjectRight = gameManager.InstantiateGameObject(); // gameObjectRight.Name = "Right"; - // gameObjectRight.Transform.Position = new Vector2(452, 0f); - // gameObjectRight.Transform.Scale = new Vector2(10f, 40f); + // gameObjectRight.Transform.Position = new Vector2D(452, 0f); + // gameObjectRight.Transform.Scale = new Vector2D(10f, 40f); // gameObjectRight.BehaviourController.AddBehaviour(); // gameObjectRight.BehaviourController.AddBehaviour(Keys.Up, Keys.Down, 268f, -268f, 400f); // gameObjectRight.BehaviourController.AddBehaviour().Assign(spriteBox); - // gameObjectRight.BehaviourController.AddBehaviour().AABBLocal = new AABB(-Vector2.One * .5f, Vector2.One * .5f); + // gameObjectRight.BehaviourController.AddBehaviour().AABBLocal = new AABB(-Vector2D.One * .5f, Vector2D.One * .5f); // engine.AddRigidBody(gameObjectRight.BehaviourController.AddBehaviour()); IGameObject goPlayAreaTop = gameManager.InstantiateGameObject(); - goPlayAreaTop.Transform.Position = new Vector2(0f, 288f + 20f); - goPlayAreaTop.Transform.Scale = new Vector2(10240f, 40f); + goPlayAreaTop.Transform.Position = new Vector2D(0f, 288f + 20f); + goPlayAreaTop.Transform.Scale = new Vector2D(10240f, 40f); // goPlayAreaTop.BehaviourController.AddBehaviour().Assign(spriteBox); - goPlayAreaTop.BehaviourController.AddBehaviour().AABBLocal = new AABB(-Vector2.One * .5f, Vector2.One * .5f); + goPlayAreaTop.BehaviourController.AddBehaviour().AABBLocal = new AABB(-Vector2D.One * .5f, Vector2D.One * .5f); engine.AddRigidBody(goPlayAreaTop.BehaviourController.AddBehaviour()); IGameObject goPlayAreaBottom = gameManager.InstantiateGameObject(); - goPlayAreaBottom.Transform.Position = new Vector2(0f, -(288f + 20f)); - goPlayAreaBottom.Transform.Scale = new Vector2(10240f, 40f); + goPlayAreaBottom.Transform.Position = new Vector2D(0f, -(288f + 20f)); + goPlayAreaBottom.Transform.Scale = new Vector2D(10240f, 40f); // goPlayAreaBottom.BehaviourController.AddBehaviour().Assign(spriteBox); - goPlayAreaBottom.BehaviourController.AddBehaviour().AABBLocal = new AABB(-Vector2.One * .5f, Vector2.One * .5f); + goPlayAreaBottom.BehaviourController.AddBehaviour().AABBLocal = new AABB(-Vector2D.One * .5f, Vector2D.One * .5f); engine.AddRigidBody(goPlayAreaBottom.BehaviourController.AddBehaviour()); IGameObject goPlayAreaRight = gameManager.InstantiateGameObject(); - goPlayAreaRight.Transform.Position = new Vector2(512f + 20f, 0f); - goPlayAreaRight.Transform.Scale = new Vector2(40f, 5760f); + goPlayAreaRight.Transform.Position = new Vector2D(512f + 20f, 0f); + goPlayAreaRight.Transform.Scale = new Vector2D(40f, 5760f); // goPlayAreaRight.BehaviourController.AddBehaviour().Assign(spriteBox); - goPlayAreaRight.BehaviourController.AddBehaviour().AABBLocal = new AABB(-Vector2.One * .5f, Vector2.One * .5f); + goPlayAreaRight.BehaviourController.AddBehaviour().AABBLocal = new AABB(-Vector2D.One * .5f, Vector2D.One * .5f); engine.AddRigidBody(goPlayAreaRight.BehaviourController.AddBehaviour()); IGameObject goPlayAreaLeft = gameManager.InstantiateGameObject(); - goPlayAreaLeft.Transform.Position = new Vector2(-(512f + 20f), 0f); - goPlayAreaLeft.Transform.Scale = new Vector2(40f, 5760f); + goPlayAreaLeft.Transform.Position = new Vector2D(-(512f + 20f), 0f); + goPlayAreaLeft.Transform.Scale = new Vector2D(40f, 5760f); // goPlayAreaLeft.BehaviourController.AddBehaviour().Assign(spriteBox); - goPlayAreaLeft.BehaviourController.AddBehaviour().AABBLocal = new AABB(-Vector2.One * .5f, Vector2.One * .5f); + goPlayAreaLeft.BehaviourController.AddBehaviour().AABBLocal = new AABB(-Vector2D.One * .5f, Vector2D.One * .5f); engine.AddRigidBody(goPlayAreaLeft.BehaviourController.AddBehaviour()); // IGameObject goPlayAreaCenter = gameManager.InstantiateGameObject(); - // goPlayAreaCenter.Transform.Position = new Vector2(100f, 100f); - // goPlayAreaCenter.Transform.Scale = new Vector2(40f, 40f); + // goPlayAreaCenter.Transform.Position = new Vector2D(100f, 100f); + // goPlayAreaCenter.Transform.Scale = new Vector2D(40f, 40f); // // goPlayAreaCenter.BehaviourController.AddBehaviour().Assign(spriteBox); // engine.AddRigidBody(goPlayAreaCenter.BehaviourController.AddBehaviour()); // TODO: use this.Content to load your game content here } - protected override void Update(GameTime gameTime) + protected override void Update(Microsoft.Xna.Framework.GameTime gameTime) { if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape)) Exit(); @@ -160,9 +160,9 @@ public class Game1 : Game gameManager.Camera.Zoom -= gameTime.ElapsedGameTime.Nanoseconds * 0.00025f; if (Keyboard.GetState().IsKeyDown(Keys.Q)) - gameManager.Camera.Rotation += gameTime.ElapsedGameTime.Nanoseconds * 0.000025f; + gameManager.Camera.Transform.Rotation += gameTime.ElapsedGameTime.Nanoseconds * 0.000025f; if (Keyboard.GetState().IsKeyDown(Keys.E)) - gameManager.Camera.Rotation -= gameTime.ElapsedGameTime.Nanoseconds * 0.000025f; + gameManager.Camera.Transform.Rotation -= gameTime.ElapsedGameTime.Nanoseconds * 0.000025f; if (Keyboard.GetState().IsKeyDown(Keys.N)) { diff --git a/Game/Physics2D/Primitives/Vector2D.cs b/Game/Physics2D/Primitives/Vector2D.cs deleted file mode 100644 index 720d1eb..0000000 --- a/Game/Physics2D/Primitives/Vector2D.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; - -namespace Syntriax.Engine.Physics2D.Primitives; - -[System.Diagnostics.DebuggerDisplay("{ToString(),nq}, Length: {Magnitude}, LengthSquared: {MagnitudeSquared}, Normalized: {Normalized}")] -public record Vector2D(float X, float Y) -{ - public float Magnitude => Length(this); - public float MagnitudeSquared => LengthSquared(this); - public Vector2D Normalized => Normalize(this); - - public readonly static Vector2D Up = new(0f, 1f); - public readonly static Vector2D Down = new(0f, -1f); - public readonly static Vector2D Left = new(-1f, 0f); - public readonly static Vector2D Right = new(1f, 0f); - public readonly static Vector2D Zero = new(0f, 0f); - public readonly static Vector2D One = new(1f, 1f); - - public static Vector2D operator -(Vector2D vector) => new(0f - vector.X, 0f - vector.Y); - public static Vector2D operator +(Vector2D left, Vector2D right) => new(left.X + right.X, left.Y + right.Y); - public static Vector2D operator -(Vector2D left, Vector2D right) => new(left.X - right.X, left.Y - right.Y); - public static Vector2D operator *(Vector2D vector, float value) => new(vector.X * value, vector.Y * value); - public static Vector2D operator *(float value, Vector2D vector) => new(vector.X * value, vector.Y * value); - public static Vector2D operator /(Vector2D vector, float value) => new(vector.X / value, vector.Y / value); - - public static float Length(Vector2D vector) => MathF.Sqrt(LengthSquared(vector)); - public static float LengthSquared(Vector2D vector) => vector.X * vector.X + vector.Y * vector.Y; - - public static float Distance(Vector2D from, Vector2D to) => Length(FromTo(from, to)); - - 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; - public static Vector2D Scale(Vector2D vector, Vector2D scale) => new(vector.X * scale.X, vector.Y * scale.Y); - - public static Vector2D Min(Vector2D left, Vector2D right) => new((left.X < right.X) ? left.X : right.X, (left.Y < right.Y) ? left.Y : right.Y); - public static Vector2D Max(Vector2D left, Vector2D right) => new((left.X > right.X) ? left.X : right.X, (left.Y > right.Y) ? left.Y : right.Y); - public static Vector2D Clamp(Vector2D vector, Vector2D min, Vector2D max) => new(Math.Clamp(vector.X, min.X, max.X), Math.Clamp(vector.Y, min.Y, max.Y)); - public static Vector2D Lerp(Vector2D from, Vector2D to, float t) => from + FromTo(from, to) * t; - - public static float Cross(Vector2D left, Vector2D right) => left.X * right.Y - left.Y * right.X; - 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; - - public override string ToString() => $"{nameof(Vector2D)}({X}, {Y})"; -} diff --git a/Game/Physics2D/Primitives/Vector2DExtensions.cs b/Game/Physics2D/Primitives/Vector2DExtensions.cs deleted file mode 100644 index a0456e5..0000000 --- a/Game/Physics2D/Primitives/Vector2DExtensions.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace Syntriax.Engine.Physics2D.Primitives; - -public static class Vector2DExtensions -{ - public static float Length(this Vector2D vector) => Vector2D.Length(vector); - public static float LengthSquared(this Vector2D vector) => Vector2D.LengthSquared(vector); - public static float Distance(this Vector2D from, Vector2D to) => Vector2D.Distance(from, to); - - 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); - public static Vector2D Scale(this Vector2D vector, Vector2D scale) => Vector2D.FromTo(vector, scale); - - public static Vector2D Min(this Vector2D left, Vector2D right) => Vector2D.Min(left, right); - public static Vector2D Max(this Vector2D left, Vector2D right) => Vector2D.Max(left, right); - public static Vector2D Clamp(this Vector2D vector, Vector2D min, Vector2D max) => Vector2D.Clamp(vector, min, max); - public static Vector2D Lerp(this Vector2D from, Vector2D to, float t) => Vector2D.Lerp(from, to, t); - - 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); -}