diff --git a/Engine.Core/Abstract/ICamera.cs b/Engine.Core/Abstract/ICamera.cs new file mode 100644 index 0000000..18934a0 --- /dev/null +++ b/Engine.Core/Abstract/ICamera.cs @@ -0,0 +1,24 @@ +using System; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace Syntriax.Engine.Core.Abstract; + +public interface ICamera +{ + Action? OnMatrixTransformChanged { get; set; } + Action? OnViewportChanged { get; set; } + Action? OnPositionChanged { get; set; } + Action? OnRotationChanged { get; set; } + Action? OnZoomChanged { get; set; } + + Matrix MatrixTransform { get; } + Viewport Viewport { get; set; } + + Vector2 Position { get; set; } + + float Rotation { get; set; } + float Zoom { get; set; } + + void Update(); +} diff --git a/Engine.Core/CameraBehaviour.cs b/Engine.Core/CameraBehaviour.cs new file mode 100644 index 0000000..d29eeb8 --- /dev/null +++ b/Engine.Core/CameraBehaviour.cs @@ -0,0 +1,98 @@ +using System; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Syntriax.Engine.Core.Abstract; + +namespace Syntriax.Engine.Core; + +public class CameraBehaviour : 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 Vector2 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 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); +} diff --git a/Engine.Core/GameManager.cs b/Engine.Core/GameManager.cs index dbc7394..9a8b25c 100644 --- a/Engine.Core/GameManager.cs +++ b/Engine.Core/GameManager.cs @@ -12,6 +12,7 @@ namespace Syntriax.Engine.Core; public class GameManager : IEntity { + public Action? OnCameraChanged { get; set; } = null; public Action? OnInitialized { get; set; } = null; public Action? OnFinalized { get; set; } = null; public Action? OnUnassigned { get; set; } = null; @@ -24,6 +25,7 @@ public class GameManager : IEntity private IStateEnable _stateEnable = null!; private GameObjectFactory _gameObjectFactory = null!; private bool _initialized = false; + private ICamera _camera = null!; private GameObjectFactory GameObjectFactory { @@ -52,6 +54,19 @@ public class GameManager : IEntity } } + public ICamera Camera + { + get => _camera; + set + { + if (_camera == value) + return; + + _camera = value; + OnCameraChanged?.Invoke(this); + } + } + public void RegisterGameObject(IGameObject gameObject) { if (_gameObjects.Contains(gameObject)) @@ -136,7 +151,7 @@ public class GameManager : IEntity public void Draw(SpriteBatch spriteBatch) { - spriteBatch.Begin(); + spriteBatch.Begin(SpriteSortMode.Deferred, transformMatrix: Camera.MatrixTransform); foreach (var drawable in _drawables) drawable.Draw(spriteBatch); diff --git a/Engine.Graphics/TwoDimensional/DisplayableSpriteBehaviour.cs b/Engine.Graphics/TwoDimensional/DisplayableSpriteBehaviour.cs index d8f4062..63bb588 100644 --- a/Engine.Graphics/TwoDimensional/DisplayableSpriteBehaviour.cs +++ b/Engine.Graphics/TwoDimensional/DisplayableSpriteBehaviour.cs @@ -86,7 +86,7 @@ public class DisplayableSpriteBehaviour : Behaviour, IDisplayableSprite, IAssign Vector2 position = transform.Position; Vector2 scale = transform.Scale; - Rectangle rectangle = new Rectangle((int)position.X, (int)position.Y, (int)(Sprite.Texture2D.Width * scale.X), (int)(Sprite.Texture2D.Height * scale.Y)); + Rectangle rectangle = new Rectangle((int)position.X, -(int)position.Y, (int)(Sprite.Texture2D.Width * scale.X), (int)(Sprite.Texture2D.Height * scale.Y)); spriteBatch.Draw(Sprite.Texture2D, rectangle, null, Color, transform.Rotation, Origin, SpriteEffects, Depth); }