From 62eddc884820bb5b89f530d9ff4b45e1edabfe92 Mon Sep 17 00:00:00 2001 From: Dylan Wilson Date: Fri, 25 May 2018 21:53:33 +1000 Subject: [PATCH] very rough platformer demo --- .../Platformer/AutofacDependencyResolver.cs | 30 ++++ Source/Demos/Platformer/Collisions/AABB.cs | 22 +++ Source/Demos/Platformer/Collisions/Body.cs | 20 +++ .../Platformer/Collisions/CollisionTester.cs | 104 ++++++++++++ .../Demos/Platformer/Collisions/Manifold.cs | 13 ++ Source/Demos/Platformer/Collisions/World.cs | 54 +++++++ .../Platformer/Components/PlayerComponent.cs | 9 ++ .../Platformer/Components/SpriteComponent.cs | 13 ++ .../Components/VelocityComponent.cs | 11 ++ Source/Demos/Platformer/EntityFactory.cs | 35 ++++ Source/Demos/Platformer/GameBase.cs | 70 ++++++++ Source/Demos/Platformer/GameMain.cs | 151 ++++++++++++++++++ .../Demos/Platformer/KeyboardInputService.cs | 35 ++++ Source/Demos/Platformer/Platformer.csproj | 11 +- Source/Demos/Platformer/Program.cs | 4 +- .../Platformer/Systems/MovementSystem.cs | 31 ++++ .../Demos/Platformer/Systems/PlayerSystem.cs | 35 ++++ .../Demos/Platformer/Systems/RenderSystem.cs | 39 +++++ 18 files changed, 677 insertions(+), 10 deletions(-) create mode 100644 Source/Demos/Platformer/AutofacDependencyResolver.cs create mode 100644 Source/Demos/Platformer/Collisions/AABB.cs create mode 100644 Source/Demos/Platformer/Collisions/Body.cs create mode 100644 Source/Demos/Platformer/Collisions/CollisionTester.cs create mode 100644 Source/Demos/Platformer/Collisions/Manifold.cs create mode 100644 Source/Demos/Platformer/Collisions/World.cs create mode 100644 Source/Demos/Platformer/Components/PlayerComponent.cs create mode 100644 Source/Demos/Platformer/Components/SpriteComponent.cs create mode 100644 Source/Demos/Platformer/Components/VelocityComponent.cs create mode 100644 Source/Demos/Platformer/EntityFactory.cs create mode 100644 Source/Demos/Platformer/GameBase.cs create mode 100644 Source/Demos/Platformer/GameMain.cs create mode 100644 Source/Demos/Platformer/KeyboardInputService.cs create mode 100644 Source/Demos/Platformer/Systems/MovementSystem.cs create mode 100644 Source/Demos/Platformer/Systems/PlayerSystem.cs create mode 100644 Source/Demos/Platformer/Systems/RenderSystem.cs diff --git a/Source/Demos/Platformer/AutofacDependencyResolver.cs b/Source/Demos/Platformer/AutofacDependencyResolver.cs new file mode 100644 index 00000000..15d3eba3 --- /dev/null +++ b/Source/Demos/Platformer/AutofacDependencyResolver.cs @@ -0,0 +1,30 @@ +using System; +using System.Linq; +using Autofac; +using MonoGame.Extended.Entities; + +namespace Platformer +{ + public class AutofacDependencyResolver : DefaultDependencyResolver + { + private readonly IContainer _container; + + public AutofacDependencyResolver(IContainer container) + { + _container = container; + } + + public override object Resolve(Type type, params object[] args) + { + if (_container.IsRegistered(type)) + { + var instance = _container.Resolve(type, args.Select((a, i) => new PositionalParameter(i, a))); + + if (instance != null) + return instance; + } + + return base.Resolve(type, args); + } + } +} \ No newline at end of file diff --git a/Source/Demos/Platformer/Collisions/AABB.cs b/Source/Demos/Platformer/Collisions/AABB.cs new file mode 100644 index 00000000..b80f7151 --- /dev/null +++ b/Source/Demos/Platformer/Collisions/AABB.cs @@ -0,0 +1,22 @@ +using Microsoft.Xna.Framework; + +namespace Platformer.Collisions +{ + // ReSharper disable once InconsistentNaming + public struct AABB + { + public AABB(Vector2 min, Vector2 max) + { + Min = min; + Max = max; + } + + public Vector2 Min; + public Vector2 Max; + public Vector2 Center => new Vector2(CenterX, CenterY); + public float CenterX => (Max.X - Min.X) / 2f; + public float CenterY => (Max.Y - Min.Y) / 2f; + public float Width => Max.X - Min.X; + public float Height => Max.Y - Min.Y; + } +} \ No newline at end of file diff --git a/Source/Demos/Platformer/Collisions/Body.cs b/Source/Demos/Platformer/Collisions/Body.cs new file mode 100644 index 00000000..1fe9c274 --- /dev/null +++ b/Source/Demos/Platformer/Collisions/Body.cs @@ -0,0 +1,20 @@ +using Microsoft.Xna.Framework; +using MonoGame.Extended.Entities; + +namespace Platformer.Collisions +{ + public enum BodyType + { + Static, Dynamic + } + + [EntityComponent] + public class Body + { + public BodyType BodyType { get; set; } = BodyType.Static; + public Vector2 Position { get; set; } + public Vector2 Velocity { get; set; } + public AABB BoundingBox => new AABB(Position - Size / 2f, Position + Size / 2f); + public Vector2 Size { get; set; } + } +} diff --git a/Source/Demos/Platformer/Collisions/CollisionTester.cs b/Source/Demos/Platformer/Collisions/CollisionTester.cs new file mode 100644 index 00000000..ce9882a7 --- /dev/null +++ b/Source/Demos/Platformer/Collisions/CollisionTester.cs @@ -0,0 +1,104 @@ +using System; +using Microsoft.Xna.Framework; +using MonoGame.Extended; + +namespace Platformer.Collisions +{ + public static class CollisionTester + { + public static bool AabbAabb(AABB a, AABB b) + { + if (a.Max.X < b.Min.X || a.Min.X > b.Max.X) + return false; + + if (a.Max.Y < b.Min.Y || a.Min.Y > b.Max.Y) + return false; + + return true; + } + + public static bool AabbAabb(Body bodyA, Body bodyB, out Manifold manifold) + { + manifold = new Manifold {BodyA = bodyA, BodyB = bodyB}; + + var aBox = bodyA.BoundingBox; + var bBox = bodyB.BoundingBox; + var vector = bodyA.Position - bodyB.Position; + + // Calculate half extents along x axis + var axExtent = (aBox.Max.X - aBox.Min.X) / 2f; + var bxExtent = (bBox.Max.X - bBox.Min.X) / 2f; + + // Calculate overlap on x axis + manifold.Overlap.X = axExtent + bxExtent - Math.Abs(vector.X); + + // SAT test on x axis + if (manifold.Overlap.X > 0) + { + // Calculate half extents along x axis for each object + var ayExtent = (aBox.Max.Y - aBox.Min.Y) / 2f; + var byExtent = (bBox.Max.Y - bBox.Min.Y) / 2f; + + // Calculate overlap on y axis + manifold.Overlap.Y = ayExtent + byExtent - Math.Abs(vector.Y); + + // SAT test on y axis + if (manifold.Overlap.Y > 0) + { + // Find out which axis is axis of least penetration + if (manifold.Overlap.X < manifold.Overlap.Y) + { + manifold.Normal = vector.X < 0 ? new Vector2(-1, 0) : new Vector2(1, 0); + manifold.Penetration = manifold.Overlap.X; + return true; + } + + // Point toward B knowing that n points from A to B + manifold.Normal = vector.Y < 0 ? new Vector2(0, -1) : new Vector2(0, 1); + manifold.Penetration = manifold.Overlap.Y; + return true; + } + } + + return false; + } + + public static bool CircleCircle(CircleF a, CircleF b) + { + var distance = a.Radius + b.Radius; + var distanceSquared = distance * distance; + var x = a.Center.X + b.Center.X; + var y = a.Center.Y + b.Center.Y; + return distanceSquared < x * x + y * y; + } + + public static bool CircleCircle(CircleF a, CircleF b, out Manifold manifold) + { + manifold = new Manifold(); + + // Vector from A to B + var vector = b.Center - a.Center; + var radiusSquared = a.Radius + b.Radius; + radiusSquared *= radiusSquared; + + if (vector.LengthSquared() > radiusSquared) + return false; + + // Circles have collided, now compute manifold + var distance = vector.Length(); + + // ReSharper disable once CompareOfFloatsByEqualityOperator + if (distance != 0) + { + manifold.Penetration = radiusSquared - distance; + manifold.Normal = vector / distance; + return true; + } + + // Circles are on same position + manifold.Penetration = a.Radius; + manifold.Normal = new Vector2(1, 0); + return true; + } + } +} diff --git a/Source/Demos/Platformer/Collisions/Manifold.cs b/Source/Demos/Platformer/Collisions/Manifold.cs new file mode 100644 index 00000000..57cc6efe --- /dev/null +++ b/Source/Demos/Platformer/Collisions/Manifold.cs @@ -0,0 +1,13 @@ +using Microsoft.Xna.Framework; + +namespace Platformer.Collisions +{ + public struct Manifold + { + public Body BodyA; + public Body BodyB; + public float Penetration; + public Vector2 Normal; + public Vector2 Overlap; + } +} \ No newline at end of file diff --git a/Source/Demos/Platformer/Collisions/World.cs b/Source/Demos/Platformer/Collisions/World.cs new file mode 100644 index 00000000..309e35a2 --- /dev/null +++ b/Source/Demos/Platformer/Collisions/World.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Xna.Framework; + +namespace Platformer.Collisions +{ + public struct CollisionPair + { + public Body BodyA; + public Body BodyB; + } + + public class World + { + public World(Vector2 gravity) + { + Gravity = gravity; + Bodies = new List(); + } + + private readonly List _collisionPairs = new List(); + + public Vector2 Gravity { get; set; } + public List Bodies { get; } + public Action OnCollision { get; set; } + + public void Update(float deltaTime) + { + foreach (var body in Bodies.Where(b => b.BodyType == BodyType.Dynamic)) + { + body.Position += body.Velocity * deltaTime; + body.Velocity += Gravity * deltaTime; + } + + foreach (var bodyA in Bodies) + { + foreach (var bodyB in Bodies.Where(b => b.BodyType == BodyType.Dynamic)) + { + if (bodyA != bodyB && CollisionTester.AabbAabb(bodyA.BoundingBox, bodyB.BoundingBox)) + _collisionPairs.Add(new CollisionPair {BodyA = bodyA, BodyB = bodyB}); + } + } + + foreach (var collisionPair in _collisionPairs) + { + if (CollisionTester.AabbAabb(collisionPair.BodyA, collisionPair.BodyB, out var manifold)) + OnCollision?.Invoke(manifold); + } + + _collisionPairs.Clear(); + } + } +} \ No newline at end of file diff --git a/Source/Demos/Platformer/Components/PlayerComponent.cs b/Source/Demos/Platformer/Components/PlayerComponent.cs new file mode 100644 index 00000000..d74adf38 --- /dev/null +++ b/Source/Demos/Platformer/Components/PlayerComponent.cs @@ -0,0 +1,9 @@ +using MonoGame.Extended.Entities; + +namespace Platformer.Components +{ + [EntityComponent] + public class PlayerComponent //: EntityComponent + { + } +} \ No newline at end of file diff --git a/Source/Demos/Platformer/Components/SpriteComponent.cs b/Source/Demos/Platformer/Components/SpriteComponent.cs new file mode 100644 index 00000000..13fc4018 --- /dev/null +++ b/Source/Demos/Platformer/Components/SpriteComponent.cs @@ -0,0 +1,13 @@ +using Microsoft.Xna.Framework; +using MonoGame.Extended.Entities; +using MonoGame.Extended.Sprites; + +namespace Platformer.Components +{ + [EntityComponent] + public class SpriteComponent //: EntityComponent + { + public Sprite Sprite { get; set; } + public Color Color { get; set; } + } +} diff --git a/Source/Demos/Platformer/Components/VelocityComponent.cs b/Source/Demos/Platformer/Components/VelocityComponent.cs new file mode 100644 index 00000000..a0636112 --- /dev/null +++ b/Source/Demos/Platformer/Components/VelocityComponent.cs @@ -0,0 +1,11 @@ +using Microsoft.Xna.Framework; +using MonoGame.Extended.Entities; + +namespace Platformer.Components +{ + [EntityComponent] + public class VelocityComponent //: EntityComponent + { + public Vector2 Velocity { get; set; } + } +} \ No newline at end of file diff --git a/Source/Demos/Platformer/EntityFactory.cs b/Source/Demos/Platformer/EntityFactory.cs new file mode 100644 index 00000000..eb388f64 --- /dev/null +++ b/Source/Demos/Platformer/EntityFactory.cs @@ -0,0 +1,35 @@ +using Microsoft.Xna.Framework; +using MonoGame.Extended; +using MonoGame.Extended.Entities; +using Platformer.Components; + +namespace Platformer +{ + public class EntityFactory + { + private readonly EntityManager _entityManager; + + public EntityFactory(EntityManager entityManager) + { + _entityManager = entityManager; + } + + public Entity CreatePlayer(Vector2 position) + { + var entity = _entityManager.CreateEntity(); + entity.Attach(s => s.Color = Color.WhiteSmoke); + entity.Attach(t => t.Position = position); + entity.Attach(); + entity.Attach(); + return entity; + } + + public Entity CreateTile(int x, int y) + { + var entity = _entityManager.CreateEntity(); + entity.Attach(s => s.Color = Color.Blue); + entity.Attach(t => t.Position = new Vector2(32 * x, 32 * y)); + return entity; + } + } +} \ No newline at end of file diff --git a/Source/Demos/Platformer/GameBase.cs b/Source/Demos/Platformer/GameBase.cs new file mode 100644 index 00000000..7ca084a8 --- /dev/null +++ b/Source/Demos/Platformer/GameBase.cs @@ -0,0 +1,70 @@ +using System.Reflection; +using Autofac; +using Microsoft.Xna.Framework; +using MonoGame.Extended.Entities; + +namespace Platformer +{ + public abstract class GameBase : Game + { + // ReSharper disable once NotAccessedField.Local + protected GraphicsDeviceManager GraphicsDeviceManager { get; } + protected IContainer Container { get; private set; } + protected EntityComponentSystem EntityComponentSystem { get; private set; } + protected KeyboardInputService KeyboardInputService { get; } + + public int Width { get; } + public int Height { get; } + + protected GameBase(int width = 800, int height = 480) + { + Width = width; + Height = height; + GraphicsDeviceManager = new GraphicsDeviceManager(this) + { + PreferredBackBufferWidth = width, + PreferredBackBufferHeight = height + }; + IsMouseVisible = true; + Window.AllowUserResizing = true; + Content.RootDirectory = "Content"; + KeyboardInputService = new KeyboardInputService(); + } + + protected override void Dispose(bool disposing) + { + EntityComponentSystem.Dispose(); + base.Dispose(disposing); + } + + protected override void Initialize() + { + var containerBuilder = new ContainerBuilder(); + + containerBuilder.RegisterInstance(KeyboardInputService); + + RegisterDependencies(containerBuilder); + Container = containerBuilder.Build(); + EntityComponentSystem = new EntityComponentSystem(this, new AutofacDependencyResolver(Container)); + EntityComponentSystem.Scan(Assembly.GetEntryAssembly(), Assembly.GetExecutingAssembly()); + + base.Initialize(); + } + + protected abstract void RegisterDependencies(ContainerBuilder builder); + + protected override void Update(GameTime gameTime) + { + KeyboardInputService.Update(); + EntityComponentSystem.Update(gameTime); + base.Update(gameTime); + } + + protected override void Draw(GameTime gameTime) + { + GraphicsDeviceManager.GraphicsDevice.Clear(Color.Black); + EntityComponentSystem.Draw(gameTime); + base.Draw(gameTime); + } + } +} \ No newline at end of file diff --git a/Source/Demos/Platformer/GameMain.cs b/Source/Demos/Platformer/GameMain.cs new file mode 100644 index 00000000..b5d4af61 --- /dev/null +++ b/Source/Demos/Platformer/GameMain.cs @@ -0,0 +1,151 @@ +using Autofac; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; +using MonoGame.Extended; +using Platformer.Collisions; +using Platformer.Systems; + +namespace Platformer +{ + public class GameMain : GameBase + { + //private EntityFactory _entityFactory; + + private SpriteBatch _spriteBatch; + private World _world; + private Body _player; + + public GameMain() + { + } + + protected override void RegisterDependencies(ContainerBuilder builder) + { + builder.RegisterInstance(new SpriteBatch(GraphicsDevice)); + builder.RegisterType(); + builder.RegisterType(); + builder.RegisterType(); + } + + protected override void LoadContent() + { + //_entityFactory = new EntityFactory(EntityComponentSystem.EntityManager); + //_entityFactory.CreatePlayer(new Vector2(400, 240)); + + //for (var x = 0; x < 25; x++) + //{ + // for (var y = 0; y < 15; y++) + // { + // if(x == 0 || y == 0 || x == 24 || y == 14) + // _entityFactory.CreateTile(x, y); + + // } + //} + + _spriteBatch = new SpriteBatch(GraphicsDevice); + _world = new World(new Vector2(0, 3600)); + + var floor = new Body + { + Position = new Vector2(400, 480-16), + Size = new Vector2(800, 16), + BodyType = BodyType.Static + }; + _world.Bodies.Add(floor); + + _player = new Body + { + Position = new Vector2(400, 240), + Size = new Vector2(32, 64), + BodyType = BodyType.Dynamic + }; + _world.Bodies.Add(_player); + } + + protected override void Update(GameTime gameTime) + { + var deltaTime = gameTime.GetElapsedSeconds(); + var currentKeyboardState = Keyboard.GetState(); + var mouseState = Mouse.GetState(); + + if (currentKeyboardState.IsKeyDown(Keys.Escape)) + Exit(); + + _world.Update(deltaTime); + _world.OnCollision = OnCollision; + + _player.Velocity = new Vector2(0, _player.Velocity.Y); + + if (KeyboardInputService.IsKeyDown(Keys.Right)) + _player.Velocity = new Vector2(350, _player.Velocity.Y); + + if (KeyboardInputService.IsKeyDown(Keys.Left)) + _player.Velocity = new Vector2(-350, _player.Velocity.Y); + + if (KeyboardInputService.IsKeyDown(Keys.Up)) + _player.Velocity = new Vector2(_player.Velocity.X, -900); + + if (KeyboardInputService.IsKeyDown(Keys.Down)) + _player.Velocity += new Vector2(0, 50) * deltaTime; + + if (mouseState.LeftButton == ButtonState.Pressed) + { + var mousePosition = new Vector2(mouseState.X, mouseState.Y); + _mouseBox = !_mouseBox.HasValue ? new AABB(mousePosition, mousePosition) : new AABB(_mouseBox.Value.Min, mousePosition); + } + else + { + if (_mouseBox.HasValue) + { + var box = _mouseBox.Value; + _world.Bodies.Add(new Body + { + BodyType = BodyType.Static, + Position = box.Min + box.Center, + Size = new Vector2(box.Width, box.Height) + }); + _mouseBox = null; + } + } + + base.Update(gameTime); + } + + private AABB? _mouseBox; + + private static void OnCollision(Manifold manifold) + { + var player = manifold.BodyB.BodyType == BodyType.Dynamic ? manifold.BodyB : manifold.BodyA; + + player.Position -= manifold.Normal * manifold.Penetration; + + if(manifold.Normal.Y < 0 || manifold.Normal.Y > 0) + player.Velocity = new Vector2(player.Velocity.X, 0); + + if (manifold.Normal.X < 0 || manifold.Normal.X > 0) + player.Velocity = new Vector2(0, player.Velocity.Y); + } + + protected override void Draw(GameTime gameTime) + { + base.Draw(gameTime); + + _spriteBatch.Begin(); + + foreach (var body in _world.Bodies) + { + var box = body.BoundingBox; + _spriteBatch.FillRectangle(new RectangleF(box.Min.X, box.Min.Y, box.Width, box.Height), body.BodyType == BodyType.Static ? Color.WhiteSmoke : Color.Green); + } + + if (_mouseBox.HasValue) + { + var box = _mouseBox.Value; + _spriteBatch.DrawRectangle(new RectangleF(box.Min.X, box.Min.Y, box.Width, box.Height), Color.Magenta); + } + + _spriteBatch.End(); + } + } +} diff --git a/Source/Demos/Platformer/KeyboardInputService.cs b/Source/Demos/Platformer/KeyboardInputService.cs new file mode 100644 index 00000000..68479fee --- /dev/null +++ b/Source/Demos/Platformer/KeyboardInputService.cs @@ -0,0 +1,35 @@ +using Microsoft.Xna.Framework.Input; + +namespace Platformer +{ + public class KeyboardInputService + { + public KeyboardInputService() + { + } + + public KeyboardState CurrentState { get; private set; } + public KeyboardState PreviousState { get; private set; } + + public bool IsKeyDown(Keys key) + { + return CurrentState.IsKeyDown(key); + } + + public bool IsKeyUp(Keys key) + { + return CurrentState.IsKeyUp(key); + } + + public bool IsKeyTapped(Keys key) + { + return PreviousState.IsKeyDown(key) && CurrentState.IsKeyUp(key); + } + + public void Update() + { + PreviousState = CurrentState; + CurrentState = Keyboard.GetState(); + } + } +} \ No newline at end of file diff --git a/Source/Demos/Platformer/Platformer.csproj b/Source/Demos/Platformer/Platformer.csproj index f8dc0d70..eeaec2b1 100644 --- a/Source/Demos/Platformer/Platformer.csproj +++ b/Source/Demos/Platformer/Platformer.csproj @@ -9,15 +9,10 @@ + + + - - - - - - - - diff --git a/Source/Demos/Platformer/Program.cs b/Source/Demos/Platformer/Program.cs index 6756c912..a84d5402 100644 --- a/Source/Demos/Platformer/Program.cs +++ b/Source/Demos/Platformer/Program.cs @@ -5,9 +5,9 @@ namespace Platformer public static class Program { [STAThread] - public static void Main() + static void Main() { - using (var game = new MainGame()) + using (var game = new GameMain()) game.Run(); } } diff --git a/Source/Demos/Platformer/Systems/MovementSystem.cs b/Source/Demos/Platformer/Systems/MovementSystem.cs new file mode 100644 index 00000000..57081661 --- /dev/null +++ b/Source/Demos/Platformer/Systems/MovementSystem.cs @@ -0,0 +1,31 @@ +using Microsoft.Xna.Framework; +using MonoGame.Extended; +using MonoGame.Extended.Entities; +using Platformer.Components; + +namespace Platformer.Systems +{ + [Aspect(AspectType.All, typeof(VelocityComponent), typeof(Transform2))] + [EntitySystem(GameLoopType.Update, Layer = 0)] + public class MovementSystem : EntityProcessingSystem + { + protected override void Process(GameTime gameTime, Entity entity) + { + var movement = entity.Get(); + var transform = entity.Get(); + + var elapsedSeconds = gameTime.GetElapsedSeconds(); + + transform.Position += movement.Velocity * elapsedSeconds; + movement.Velocity += new Vector2(0, 1600) * elapsedSeconds; + + const int floor = 480 - 64; + + if (transform.Position.Y >= floor) + { + movement.Velocity = new Vector2(movement.Velocity.X, 0); + transform.Position = new Vector2(transform.Position.X, floor); + } + } + } +} \ No newline at end of file diff --git a/Source/Demos/Platformer/Systems/PlayerSystem.cs b/Source/Demos/Platformer/Systems/PlayerSystem.cs new file mode 100644 index 00000000..158094ab --- /dev/null +++ b/Source/Demos/Platformer/Systems/PlayerSystem.cs @@ -0,0 +1,35 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Input; +using MonoGame.Extended.Entities; +using Platformer.Components; + +namespace Platformer.Systems +{ + [Aspect(AspectType.All, typeof(VelocityComponent), typeof(PlayerComponent))] + [EntitySystem(GameLoopType.Update, Layer = 0)] + public class PlayerSystem : EntityProcessingSystem + { + private readonly KeyboardInputService _inputService; + + public PlayerSystem(KeyboardInputService inputService) + { + _inputService = inputService; + } + + protected override void Process(GameTime gameTime, Entity entity) + { + var movement = entity.Get(); + + movement.Velocity = new Vector2(0, movement.Velocity.Y); + + if (_inputService.IsKeyDown(Keys.Left) || _inputService.IsKeyDown(Keys.A)) + movement.Velocity = new Vector2(-260, movement.Velocity.Y); + + if (_inputService.IsKeyDown(Keys.Right) || _inputService.IsKeyDown(Keys.D)) + movement.Velocity = new Vector2(260, movement.Velocity.Y); + + if (_inputService.IsKeyTapped(Keys.Up) || _inputService.IsKeyTapped(Keys.W)) + movement.Velocity = new Vector2(movement.Velocity.X, -600); + } + } +} \ No newline at end of file diff --git a/Source/Demos/Platformer/Systems/RenderSystem.cs b/Source/Demos/Platformer/Systems/RenderSystem.cs new file mode 100644 index 00000000..af21d385 --- /dev/null +++ b/Source/Demos/Platformer/Systems/RenderSystem.cs @@ -0,0 +1,39 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using MonoGame.Extended; +using MonoGame.Extended.Entities; +using Platformer.Components; + +namespace Platformer.Systems +{ + [Aspect(AspectType.All, typeof(SpriteComponent), typeof(Transform2))] + [EntitySystem(GameLoopType.Draw, Layer = 0)] + public class RenderSystem : EntityProcessingSystem + { + private readonly SpriteBatch _spriteBatch; + + public RenderSystem(SpriteBatch spriteBatch) + { + _spriteBatch = spriteBatch; + } + + protected override void Begin(GameTime gameTime) + { + _spriteBatch.Begin(); + } + + protected override void Process(GameTime gameTime, Entity entity) + { + var sprite = entity.Get(); + var transform = entity.Get(); + + _spriteBatch.FillRectangle(new RectangleF(transform.Position, new Size2(32f, 32f)), sprite.Color); + //_spriteBatch.Draw(sprite.Sprite); + } + + protected override void End(GameTime gameTime) + { + _spriteBatch.End(); + } + } +}