diff --git a/Engine b/Engine index 39e553e..d08495a 160000 --- a/Engine +++ b/Engine @@ -1 +1 @@ -Subproject commit 39e553ebbf61f398a3ed9a96b20f6819a197cd86 +Subproject commit d08495afbb7ca9f1afa2c8edcdaf0786bf095e9d diff --git a/Game/EngineConverter.cs b/Game/EngineConverter.cs index 3e75700..6e5aed4 100644 --- a/Game/EngineConverter.cs +++ b/Game/EngineConverter.cs @@ -8,4 +8,8 @@ public static class EngineConverter { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static EngineTime ToEngineTime(this GameTime gameTime) => new(gameTime.TotalGameTime, gameTime.ElapsedGameTime); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2D ToVector2D(this Vector2 vector) => new(vector.X, vector.Y); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector2 ToVector2(this Vector2D vector) => new(vector.X, vector.Y); } diff --git a/Game/Game1.cs b/Game/Game1.cs index 7e06d96..0144dc0 100644 --- a/Game/Game1.cs +++ b/Game/Game1.cs @@ -7,6 +7,7 @@ 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; @@ -18,8 +19,8 @@ public class Game1 : Game private PhysicsEngine2D engine; private SpriteBatch _spriteBatch = null!; public static GameManager gameManager = null!; - // public static Sprite spriteBox = null!; - private MonoGameCameraBehaviour cameraBehaviour; + public static Sprite spriteBox = null!; + private MonoGameCameraBehaviour cameraBehaviour = null!; public Game1() @@ -50,8 +51,8 @@ public class Game1 : Game { _spriteBatch = new SpriteBatch(GraphicsDevice); - // spriteBox = new Sprite() { Texture2D = Content.Load("Sprites/Pixel") }; - // Sprite spriteBall = new Sprite() { Texture2D = Content.Load("Sprites/Circle") }; + spriteBox = new Sprite() { Texture2D = Content.Load("Sprites/Pixel") }; + Sprite spriteBall = new Sprite() { Texture2D = Content.Load("Sprites/Circle") }; IGameObject gameObjectCamera = gameManager.InstantiateGameObject(); gameObjectCamera.Name = "Camera"; @@ -67,7 +68,7 @@ public class Game1 : Game gameObjectBall.Transform.Scale = new Vector2D(1f / 51.2f, 1f / 51.2f); engine.AddRigidBody(gameObjectBall.BehaviourController.AddBehaviour()); gameObjectBall.BehaviourController.AddBehaviour(new Vector2D(.1f, .1f), 500f); - // gameObjectBall.BehaviourController.AddBehaviour().Assign(spriteBall); + gameObjectBall.BehaviourController.AddBehaviour().Assign(spriteBall); gameObjectBall.BehaviourController.AddBehaviour().AABBLocal = new AABB(-Vector2D.One * 512f * .5f, Vector2D.One * 512f * .5f); // gameObjectBall = gameManager.InstantiateGameObject(); // gameObjectBall.Name = "Ball"; @@ -102,26 +103,26 @@ public class Game1 : Game IGameObject goPlayAreaTop = gameManager.InstantiateGameObject(); goPlayAreaTop.Transform.Position = new Vector2D(0f, 288f + 20f); goPlayAreaTop.Transform.Scale = new Vector2D(10240f, 40f); - // goPlayAreaTop.BehaviourController.AddBehaviour().Assign(spriteBox); + goPlayAreaTop.BehaviourController.AddBehaviour().Assign(spriteBox); // 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 Vector2D(0f, -(288f + 20f)); goPlayAreaBottom.Transform.Scale = new Vector2D(10240f, 40f); - // goPlayAreaBottom.BehaviourController.AddBehaviour().Assign(spriteBox); + goPlayAreaBottom.BehaviourController.AddBehaviour().Assign(spriteBox); // 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 Vector2D(512f + 20f, 0f); goPlayAreaRight.Transform.Scale = new Vector2D(40f, 5760f); - // goPlayAreaRight.BehaviourController.AddBehaviour().Assign(spriteBox); + goPlayAreaRight.BehaviourController.AddBehaviour().Assign(spriteBox); // 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 Vector2D(-(512f + 20f), 0f); goPlayAreaLeft.Transform.Scale = new Vector2D(40f, 5760f); - // goPlayAreaLeft.BehaviourController.AddBehaviour().Assign(spriteBox); + goPlayAreaLeft.BehaviourController.AddBehaviour().Assign(spriteBox); // goPlayAreaLeft.BehaviourController.AddBehaviour().AABBLocal = new AABB(-Vector2D.One * .5f, Vector2D.One * .5f); engine.AddRigidBody(goPlayAreaLeft.BehaviourController.AddBehaviour()); @@ -227,7 +228,16 @@ public class Game1 : Game // TODO: Add your drawing code here gameManager.PreDraw(); gameManager.Camera.Update(); - // gameManager.Draw(_spriteBatch); + + _spriteBatch.Begin(SpriteSortMode.Deferred, transformMatrix: cameraBehaviour.MatrixTransform); + foreach (IGameObject gameObject in gameManager) + { + if (!gameObject.BehaviourController.TryGetBehaviour(out IDisplayable? displayable)) + continue; + + displayable.Draw(_spriteBatch); + } + _spriteBatch.End(); base.Draw(gameTime); } diff --git a/Game/Graphics/Abstract/Assignable/IAssignableSprite.cs b/Game/Graphics/Abstract/Assignable/IAssignableSprite.cs new file mode 100644 index 0000000..8f05c68 --- /dev/null +++ b/Game/Graphics/Abstract/Assignable/IAssignableSprite.cs @@ -0,0 +1,26 @@ +using System; + +namespace Syntriax.Engine.Core.Abstract; + +/// +/// Indicates the object is an with an assignable field. +/// +public interface IAssignableSprite : IAssignable +{ + /// + /// Callback triggered when the value has has been assigned a new value. + /// + Action? OnSpriteAssigned { get; set; } + + /// + ISprite Sprite { get; } + + /// + /// Assign a value to the field of this object + /// + /// New to assign. + /// + /// , if the value given assigned successfully assigned, if not. + /// + bool Assign(ISprite sprite); +} diff --git a/Game/Graphics/Abstract/ISprite.cs b/Game/Graphics/Abstract/ISprite.cs new file mode 100644 index 0000000..feb19e8 --- /dev/null +++ b/Game/Graphics/Abstract/ISprite.cs @@ -0,0 +1,13 @@ +using System; + +using Microsoft.Xna.Framework.Graphics; + +namespace Syntriax.Engine.Core.Abstract; + +// TODO Probably gonna have to rethink this +public interface ISprite +{ + Action? OnTextureChanged { get; set; } + + Texture2D Texture2D { get; set; } +} diff --git a/Game/Graphics/Sprite.cs b/Game/Graphics/Sprite.cs new file mode 100644 index 0000000..5adcdd3 --- /dev/null +++ b/Game/Graphics/Sprite.cs @@ -0,0 +1,27 @@ +using System; + +using Microsoft.Xna.Framework.Graphics; + +using Syntriax.Engine.Core.Abstract; + +namespace Syntriax.Engine.Core; + +public class Sprite : ISprite +{ + public Action? OnTextureChanged { get; set; } + + private Texture2D _texture = null!; + + public Texture2D Texture2D + { + get => _texture; + set + { + if (_texture == value) + return; + + _texture = value; + OnTextureChanged?.Invoke(this); + } + } +} diff --git a/Game/Graphics/TwoDimensional/Abstract/IDisplayable.cs b/Game/Graphics/TwoDimensional/Abstract/IDisplayable.cs new file mode 100644 index 0000000..d27a812 --- /dev/null +++ b/Game/Graphics/TwoDimensional/Abstract/IDisplayable.cs @@ -0,0 +1,8 @@ +using Microsoft.Xna.Framework.Graphics; + +namespace Syntriax.Engine.Core.Abstract; + +public interface IDisplayable +{ + public void Draw(SpriteBatch spriteBatch); +} diff --git a/Game/Graphics/TwoDimensional/Abstract/IDisplayableSprite.cs b/Game/Graphics/TwoDimensional/Abstract/IDisplayableSprite.cs new file mode 100644 index 0000000..83b8215 --- /dev/null +++ b/Game/Graphics/TwoDimensional/Abstract/IDisplayableSprite.cs @@ -0,0 +1,20 @@ +using System; + +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +using Syntriax.Engine.Core.Abstract; + +namespace Syntriax.Engine.Graphics.TwoDimensional.Abstract; +public interface IDisplayableSprite : IDisplayable, IAssignableSprite +{ + Action? OnSpriteEffectsChanged { get; set; } + Action? OnOriginChanged { get; set; } + Action? OnColorChanged { get; set; } + Action? OnDepthChanged { get; set; } + + SpriteEffects SpriteEffects { get; set; } + Vector2 Origin { get; set; } + Color Color { get; set; } + float Depth { get; set; } +} diff --git a/Game/Graphics/TwoDimensional/DisplayableSpriteBehaviour.cs b/Game/Graphics/TwoDimensional/DisplayableSpriteBehaviour.cs new file mode 100644 index 0000000..05b2d0d --- /dev/null +++ b/Game/Graphics/TwoDimensional/DisplayableSpriteBehaviour.cs @@ -0,0 +1,117 @@ +using System; + +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +using Syntriax.Engine.Core; +using Syntriax.Engine.Core.Abstract; +using Syntriax.Engine.Graphics.TwoDimensional.Abstract; + +namespace Syntriax.Engine.Graphics.TwoDimensional; + +public class DisplayableSpriteBehaviour : Behaviour, IDisplayableSprite, IAssignableSprite +{ + public Action? OnSpriteAssigned { get; set; } = null; + public Action? OnSpriteEffectsChanged { get; set; } = null; + public Action? OnOriginChanged { get; set; } = null; + public Action? OnColorChanged { get; set; } = null; + public Action? OnDepthChanged { get; set; } = null; + + private ISprite _sprite = null!; + private Color _color = Color.White; + private float _depth = 0f; + private SpriteEffects _spriteEffects = SpriteEffects.None; + private Vector2 _origin = Vector2.One * .5f; + + + public ISprite Sprite => _sprite; + + public SpriteEffects SpriteEffects + { + get => _spriteEffects; + set + { + if (_spriteEffects == value) + return; + + _spriteEffects = value; + OnSpriteEffectsChanged?.Invoke(this); + } + } + + public Vector2 Origin + { + get => _origin; + set + { + if (_origin == value) + return; + + _origin = value; + OnOriginChanged?.Invoke(this); + } + } + + public Color Color + { + get => _color; + set + { + if (_color == value) + return; + + _color = value; + OnColorChanged?.Invoke(this); + } + } + + public float Depth + { + get => _depth; + set + { + if (_depth == value) + return; + + _depth = value; + OnDepthChanged?.Invoke(this); + } + } + + public void Draw(SpriteBatch spriteBatch) + { + if (!BehaviourController.GameObject.StateEnable.Enabled || !StateEnable.Enabled) + return; + + ITransform transform = BehaviourController.GameObject.Transform; + Vector2D position = transform.Position; + Vector2D scale = transform.Scale; + + Rectangle rectangle = new((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, new Vector2(Sprite.Texture2D.Width, Sprite.Texture2D.Height) * Origin, SpriteEffects, Depth); + } + + public bool Assign(ISprite sprite) + { + _sprite = sprite; + OnSpriteAssigned?.Invoke(this); + return true; + } + + public DisplayableSpriteBehaviour() => OnUnassigned += OnUnassign; + public DisplayableSpriteBehaviour( + Color? color = null, + float? depth = null, + SpriteEffects? spriteEffects = null, + Vector2? origin = null) + { + OnUnassigned += OnUnassign; + + _color = color ?? _color; + _depth = depth ?? _depth; + _spriteEffects = spriteEffects ?? _spriteEffects; + _origin = origin ?? _origin; + } + private void OnUnassign(IAssignable assignable) => _sprite = null!; +}