diff --git a/Source/Demos/Platformer/EntityFactory.cs b/Source/Demos/Platformer/EntityFactory.cs index db2caa11..959b3a94 100644 --- a/Source/Demos/Platformer/EntityFactory.cs +++ b/Source/Demos/Platformer/EntityFactory.cs @@ -4,7 +4,6 @@ using Microsoft.Xna.Framework.Graphics; using MonoGame.Extended; using MonoGame.Extended.Animations; using MonoGame.Extended.Animations.SpriteSheets; -using MonoGame.Extended.Entities; using MonoGame.Extended.Entities.Legacy; using MonoGame.Extended.TextureAtlases; using Platformer.Collisions; diff --git a/Source/Demos/Platformer/GameMain.cs b/Source/Demos/Platformer/GameMain.cs index 35db88ac..a90a0186 100644 --- a/Source/Demos/Platformer/GameMain.cs +++ b/Source/Demos/Platformer/GameMain.cs @@ -2,7 +2,6 @@ using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using MonoGame.Extended; -using MonoGame.Extended.Entities; using MonoGame.Extended.Entities.Legacy; using MonoGame.Extended.Tiled; using MonoGame.Extended.Tiled.Renderers; diff --git a/Source/Demos/Platformer/Systems/PlayerSystem.cs b/Source/Demos/Platformer/Systems/PlayerSystem.cs index a80811f7..3cc1ee23 100644 --- a/Source/Demos/Platformer/Systems/PlayerSystem.cs +++ b/Source/Demos/Platformer/Systems/PlayerSystem.cs @@ -4,7 +4,6 @@ using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using MonoGame.Extended; using MonoGame.Extended.Animations; -using MonoGame.Extended.Entities; using MonoGame.Extended.Entities.Legacy; using MonoGame.Extended.Input; using Platformer.Collisions; diff --git a/Source/Demos/Platformer/Systems/RenderSystem.cs b/Source/Demos/Platformer/Systems/RenderSystem.cs index a76f7d55..4dd045c1 100644 --- a/Source/Demos/Platformer/Systems/RenderSystem.cs +++ b/Source/Demos/Platformer/Systems/RenderSystem.cs @@ -2,7 +2,6 @@ using Microsoft.Xna.Framework.Graphics; using MonoGame.Extended; using MonoGame.Extended.Animations; -using MonoGame.Extended.Entities; using MonoGame.Extended.Entities.Legacy; using MonoGame.Extended.Sprites; diff --git a/Source/Demos/Platformer/Systems/WorldSystem.cs b/Source/Demos/Platformer/Systems/WorldSystem.cs index faa0189a..73fac24c 100644 --- a/Source/Demos/Platformer/Systems/WorldSystem.cs +++ b/Source/Demos/Platformer/Systems/WorldSystem.cs @@ -1,6 +1,5 @@ using Microsoft.Xna.Framework; using MonoGame.Extended; -using MonoGame.Extended.Entities; using MonoGame.Extended.Entities.Legacy; using Platformer.Collisions; diff --git a/Source/Demos/Sandbox/Content/Content.mgcb b/Source/Demos/Sandbox/Content/Content.mgcb index 3b1872f9..f390b809 100644 --- a/Source/Demos/Sandbox/Content/Content.mgcb +++ b/Source/Demos/Sandbox/Content/Content.mgcb @@ -26,18 +26,6 @@ /processorParam:TextureFormat=Color /build:ballGrey.png -#begin court.png -/importer:TextureImporter -/processor:TextureProcessor -/processorParam:ColorKeyColor=255,0,255,255 -/processorParam:ColorKeyEnabled=True -/processorParam:GenerateMipmaps=False -/processorParam:PremultiplyAlpha=True -/processorParam:ResizeToPowerOfTwo=False -/processorParam:MakeSquare=False -/processorParam:TextureFormat=Color -/build:court.png - #begin kenney-rocket-square.fnt /importer:BitmapFontImporter /processor:BitmapFontProcessor @@ -55,45 +43,3 @@ /processorParam:TextureFormat=Color /build:kenney-rocket-square_0.png -#begin paddleBlue.png -/importer:TextureImporter -/processor:TextureProcessor -/processorParam:ColorKeyColor=255,0,255,255 -/processorParam:ColorKeyEnabled=True -/processorParam:GenerateMipmaps=False -/processorParam:PremultiplyAlpha=True -/processorParam:ResizeToPowerOfTwo=False -/processorParam:MakeSquare=False -/processorParam:TextureFormat=Color -/build:paddleBlue.png - -#begin paddleRed.png -/importer:TextureImporter -/processor:TextureProcessor -/processorParam:ColorKeyColor=255,0,255,255 -/processorParam:ColorKeyEnabled=True -/processorParam:GenerateMipmaps=False -/processorParam:PremultiplyAlpha=True -/processorParam:ResizeToPowerOfTwo=False -/processorParam:MakeSquare=False -/processorParam:TextureFormat=Color -/build:paddleRed.png - -#begin pip.wav -/importer:WavImporter -/processor:SoundEffectProcessor -/processorParam:Quality=Best -/build:pip.wav - -#begin title-screen.png -/importer:TextureImporter -/processor:TextureProcessor -/processorParam:ColorKeyColor=255,0,255,255 -/processorParam:ColorKeyEnabled=True -/processorParam:GenerateMipmaps=False -/processorParam:PremultiplyAlpha=True -/processorParam:ResizeToPowerOfTwo=False -/processorParam:MakeSquare=False -/processorParam:TextureFormat=Color -/build:title-screen.png - diff --git a/Source/Demos/Sandbox/Content/court.png b/Source/Demos/Sandbox/Content/court.png deleted file mode 100644 index 06f4a523..00000000 Binary files a/Source/Demos/Sandbox/Content/court.png and /dev/null differ diff --git a/Source/Demos/Sandbox/Content/paddleBlue.png b/Source/Demos/Sandbox/Content/paddleBlue.png deleted file mode 100644 index 132cef3f..00000000 Binary files a/Source/Demos/Sandbox/Content/paddleBlue.png and /dev/null differ diff --git a/Source/Demos/Sandbox/Content/paddleRed.png b/Source/Demos/Sandbox/Content/paddleRed.png deleted file mode 100644 index f51f1985..00000000 Binary files a/Source/Demos/Sandbox/Content/paddleRed.png and /dev/null differ diff --git a/Source/Demos/Sandbox/Content/pip.wav b/Source/Demos/Sandbox/Content/pip.wav deleted file mode 100644 index ee26c6d5..00000000 Binary files a/Source/Demos/Sandbox/Content/pip.wav and /dev/null differ diff --git a/Source/Demos/Sandbox/Content/title-screen.png b/Source/Demos/Sandbox/Content/title-screen.png deleted file mode 100644 index cdf228a0..00000000 Binary files a/Source/Demos/Sandbox/Content/title-screen.png and /dev/null differ diff --git a/Source/Demos/Sandbox/GameMain.cs b/Source/Demos/Sandbox/GameMain.cs index 2d602193..a35cc05e 100644 --- a/Source/Demos/Sandbox/GameMain.cs +++ b/Source/Demos/Sandbox/GameMain.cs @@ -1,156 +1,92 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; using MonoGame.Extended; -using MonoGame.Extended.Screens; -using MonoGame.Extended.Screens.Transitions; -using Sandbox.Screens; +using MonoGame.Extended.Entities; +using MonoGame.Extended.Entities.Systems; namespace Sandbox { - public class EcsAspect + public class MyRenderSystem : DrawSystem { - private readonly BitArray _allSet; - private readonly BitArray _exclusionSet; - private readonly BitArray _oneSet; + private readonly SpriteBatch _spriteBatch; + private ComponentMapper _transformMapper; - private const int _defaultSize = 32; - - public EcsAspect() + public MyRenderSystem(GraphicsDevice graphicsDevice) { - _allSet = new BitArray(_defaultSize); - _exclusionSet = new BitArray(_defaultSize); - _oneSet = new BitArray(_defaultSize); + _spriteBatch = new SpriteBatch(graphicsDevice); } - public void All(bool[] set) + public override void Initialize(ComponentManager componentManager) { - for (var i = 0; i < set.Length; i++) - _allSet.Set(i, set[i]); - } - - public bool IsInterested(EcsEntity entity) - { - return IsInterested(entity.ComponentBits); - } - - public bool IsInterested(BitArray componentBits) - { - if (componentBits.And(_allSet) == componentBits) - return true; - - return false; - } - } - - public abstract class EcsSystem - { - public virtual void Update(GameTime gameTime) { } - public virtual void Draw(GameTime gameTime) { } - } - - public class EcsEntity - { - internal EcsEntity() - { - ComponentBits = new BitArray(32); - } - - public BitArray ComponentBits { get; } - - public void Attach() - where T : class - { - } - - public void Attach(T component) - where T : class - { - } - - public void Detach() - { - } - - public T Get() - { - throw new NotImplementedException(); - } - } - - public class EcsWorld : DrawableGameComponent - { - private readonly List _entities = new List(); - private readonly List _systems = new List(); - - public EcsWorld(Game game) - : base(game) - { - } - - public EcsEntity CreateEntity() - { - var entity = new EcsEntity(); - _entities.Add(entity); - return entity; - } - - public void DestroyEntity(EcsEntity entity) - { - _entities.Remove(entity); - } - - public void AddSystem(EcsSystem system) - { - _systems.Add(system); - } - - public void RemoveSystem(EcsSystem system) - { - _systems.Remove(system); - } - - public override void Update(GameTime gameTime) - { - foreach (var system in _systems) - system.Update(gameTime); + _transformMapper = componentManager.GetMapper(); } public override void Draw(GameTime gameTime) { - foreach (var system in _systems) - system.Draw(gameTime); + _spriteBatch.Begin(samplerState: SamplerState.PointClamp); + + foreach (var entity in World.EntityManager.Entities) + { + var transform = _transformMapper.GetComponent(entity); + + _spriteBatch.DrawRectangle(transform.Position, new Size2(100, 100), Color.Black); + } + + _spriteBatch.End(); } + } - public class GameMain : Game + public class MainGame : Game { // ReSharper disable once NotAccessedField.Local - private readonly GraphicsDeviceManager _graphics; - private readonly ScreenManager _screenManager; + private GraphicsDeviceManager _graphicsDeviceManager; + private SpriteBatch _spriteBatch; + private EntityWorld _world; - public GameMain() + public MainGame() { - _graphics = new GraphicsDeviceManager(this) - { - PreferredBackBufferWidth = 800, - PreferredBackBufferHeight = 480, - SynchronizeWithVerticalRetrace = false - }; - + _graphicsDeviceManager = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; - IsFixedTimeStep = true; - TargetElapsedTime = TimeSpan.FromSeconds(1f / 60f); - - _screenManager = Components.Add(); + IsMouseVisible = true; } protected override void LoadContent() { - base.LoadContent(); + _spriteBatch = new SpriteBatch(GraphicsDevice); + _world = new EntityWorld(); + _world.RegisterSystem(new MyRenderSystem(GraphicsDevice)); - _screenManager.LoadScreen(new TitleScreen(this), new FadeTransition(GraphicsDevice, Color.Black, 0.5f)); + var entity = _world.CreateEntity(); + entity.Attach(new Transform2(new Vector2(400, 240))); + + } + + protected override void UnloadContent() + { + _spriteBatch.Dispose(); + } + + protected override void Update(GameTime gameTime) + { + var keyboardState = Keyboard.GetState(); + + if (keyboardState.IsKeyDown(Keys.Escape)) + Exit(); + + _world.Update(gameTime); + + base.Update(gameTime); + } + + protected override void Draw(GameTime gameTime) + { + GraphicsDevice.Clear(Color.CornflowerBlue); + + _world.Draw(gameTime); + + base.Draw(gameTime); } } } diff --git a/Source/Demos/Sandbox/GameObjects/Ball.cs b/Source/Demos/Sandbox/GameObjects/Ball.cs deleted file mode 100644 index d0016b0b..00000000 --- a/Source/Demos/Sandbox/GameObjects/Ball.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Microsoft.Xna.Framework; - -namespace Sandbox.GameObjects -{ - public class Ball : GameObject - { - public Vector2 Velocity; - } -} \ No newline at end of file diff --git a/Source/Demos/Sandbox/GameObjects/GameObject.cs b/Source/Demos/Sandbox/GameObjects/GameObject.cs deleted file mode 100644 index 204932e9..00000000 --- a/Source/Demos/Sandbox/GameObjects/GameObject.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Microsoft.Xna.Framework; -using MonoGame.Extended; -using MonoGame.Extended.Sprites; - -namespace Sandbox.GameObjects -{ - public class GameObject - { - public Vector2 Position; - public Vector2 Scale = Vector2.One; - public float Rotation; - public Sprite Sprite; - public RectangleF BoundingRectangle => Sprite.GetBoundingRectangle(Position, 0, Vector2.One); - } -} \ No newline at end of file diff --git a/Source/Demos/Sandbox/GameObjects/Paddle.cs b/Source/Demos/Sandbox/GameObjects/Paddle.cs deleted file mode 100644 index d59a641b..00000000 --- a/Source/Demos/Sandbox/GameObjects/Paddle.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Sandbox.GameObjects -{ - public class Paddle : GameObject - { - } -} \ No newline at end of file diff --git a/Source/Demos/Sandbox/Program.cs b/Source/Demos/Sandbox/Program.cs index e4bb48f1..fc856a78 100644 --- a/Source/Demos/Sandbox/Program.cs +++ b/Source/Demos/Sandbox/Program.cs @@ -5,9 +5,9 @@ namespace Sandbox public static class Program { [STAThread] - private static void Main() + public static void Main() { - using (var game = new GameMain()) + using (var game = new MainGame()) game.Run(); } } diff --git a/Source/Demos/Sandbox/Sandbox.csproj b/Source/Demos/Sandbox/Sandbox.csproj index 30f19912..1e77675a 100644 --- a/Source/Demos/Sandbox/Sandbox.csproj +++ b/Source/Demos/Sandbox/Sandbox.csproj @@ -10,6 +10,7 @@ + diff --git a/Source/Demos/Sandbox/Screens/PongGameScreen.cs b/Source/Demos/Sandbox/Screens/PongGameScreen.cs deleted file mode 100644 index f6cbd7c6..00000000 --- a/Source/Demos/Sandbox/Screens/PongGameScreen.cs +++ /dev/null @@ -1,240 +0,0 @@ -using System; -using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Audio; -using Microsoft.Xna.Framework.Graphics; -using Microsoft.Xna.Framework.Input; -using MonoGame.Extended; -using MonoGame.Extended.BitmapFonts; -using MonoGame.Extended.Input; -using MonoGame.Extended.Screens; -using MonoGame.Extended.Screens.Transitions; -using MonoGame.Extended.Sprites; -using MonoGame.Extended.Tweening; -using Sandbox.GameObjects; - -namespace Sandbox.Screens -{ - public class PongGameScreen : GameScreen - { - private SpriteBatch _spriteBatch; - private Paddle _bluePaddle; - private Paddle _redPaddle; - private Ball _ball; - private Texture2D _court; - private BitmapFont _font; - private SoundEffect _plopSoundEffect; - private int _leftScore; - private int _rightScore; - private readonly FastRandom _random = new FastRandom(); - private Tweener _tweener = new Tweener(); - - public PongGameScreen(Game game) - : base(game) - { - game.IsMouseVisible = false; - } - - public int ScreenWidth => GraphicsDevice.Viewport.Width; - public int ScreenHeight => GraphicsDevice.Viewport.Height; - - public override void LoadContent() - { - base.LoadContent(); - - _spriteBatch = new SpriteBatch(GraphicsDevice); - _plopSoundEffect = Content.Load("pip"); - _font = Content.Load("kenney-rocket-square"); - _court = Content.Load("court"); - - _bluePaddle = new Paddle - { - Position = new Vector2(50, ScreenWidth / 2f), - Sprite = new Sprite(Content.Load("paddleBlue")) - }; - - _redPaddle = new Paddle - { - Position = new Vector2(ScreenWidth - 50, ScreenHeight / 2f), - Sprite = new Sprite(Content.Load("paddleRed")) - }; - - _ball = new Ball - { - Position = new Vector2(ScreenWidth / 2f, ScreenHeight / 2f), - Sprite = new Sprite(Content.Load("ballGrey")), - Velocity = new Vector2(250, 200) - }; - } - - public override void UnloadContent() - { - base.UnloadContent(); - _spriteBatch.Dispose(); - } - - public override void Update(GameTime gameTime) - { - var elapsedSeconds = gameTime.GetElapsedSeconds(); - var mouseState = MouseExtended.GetState(); - var keyboardState = KeyboardExtended.GetState(); - - if (keyboardState.WasKeyJustDown(Keys.Escape)) - ScreenManager.LoadScreen(new TitleScreen(Game), new ExpandTransition(GraphicsDevice, Color.Black)); - - MovePaddlePlayer(mouseState); - - MovePaddleAi(_redPaddle, elapsedSeconds); - - ConstrainPaddle(_bluePaddle); - ConstrainPaddle(_redPaddle); - - MoveBall(elapsedSeconds); - - if (BallHitPaddle(_ball, _bluePaddle)) - { - // TODO: Change the angle of the bounce - //_tweener.TweenTo(_bluePaddle, p => p.Rotation, MathHelper.Pi / 16f, 0.2f) - // //.OnSet(v => new Vector2(v.X, _bluePaddle.Position.Y)) - // .RepeatReverse() - // .Easing(EasingFunctions.ExponentialIn); - - _plopSoundEffect.Play(1.0f, _random.NextSingle(0.5f, 1.0f), -1f); - } - - if (BallHitPaddle(_ball, _redPaddle)) - { - // TODO: Change the angle of the bounce - - //_tweener.TweenTo(_redPaddle, p => p.Position, _redPaddle.Position + new Vector2(15, 0), 0.2f) - // .RepeatReverse() - // .Easing(EasingFunctions.ExponentialIn); - - _plopSoundEffect.Play(1f, _random.NextSingle(-1f, 1f), 1f); - } - - _tweener.Update(elapsedSeconds); - } - - public override void Draw(GameTime gameTime) - { - _spriteBatch.Begin(samplerState: SamplerState.PointClamp); - _spriteBatch.Draw(_court, new Rectangle(0, 0, ScreenWidth, ScreenHeight), Color.White); - - DrawScores(); - - _spriteBatch.Draw(_redPaddle.Sprite, _redPaddle.Position, _redPaddle.Rotation, _redPaddle.Scale); - _spriteBatch.Draw(_bluePaddle.Sprite, _bluePaddle.Position, _bluePaddle.Rotation, _bluePaddle.Scale); - _spriteBatch.Draw(_ball.Sprite, _ball.Position, _ball.Rotation, _ball.Scale); - _spriteBatch.End(); - } - - private void DrawScores() - { - _spriteBatch.DrawString(_font, $"{_leftScore:00}", new Vector2(172, 10), new Color(0.2f, 0.2f, 0.2f), 0, Vector2.Zero, Vector2.One * 4f, SpriteEffects.None, 0); - _spriteBatch.DrawString(_font, $"{_rightScore:00}", new Vector2(430, 10), new Color(0.2f, 0.2f, 0.2f), 0, Vector2.Zero, Vector2.One * 4f, SpriteEffects.None, 0); - } - - private void MovePaddlePlayer(MouseStateExtended mouseState) - { - _bluePaddle.Position.Y = mouseState.Position.Y; - } - - private static bool BallHitPaddle(Ball ball, Paddle paddle) - { - if (ball.BoundingRectangle.Intersects(paddle.BoundingRectangle)) - { - if (ball.BoundingRectangle.Left < paddle.BoundingRectangle.Left) - ball.Position.X = paddle.BoundingRectangle.Left - ball.BoundingRectangle.Width / 2; - - if (ball.BoundingRectangle.Right > paddle.BoundingRectangle.Right) - ball.Position.X = paddle.BoundingRectangle.Right + ball.BoundingRectangle.Width / 2; - - ball.Velocity.X = -ball.Velocity.X; - return true; - } - - return false; - } - - private void MoveBall(float elapsedSeconds) - { - _ball.Position += _ball.Velocity * elapsedSeconds; - - var halfHeight = _ball.BoundingRectangle.Height / 2; - var halfWidth = _ball.BoundingRectangle.Width / 2; - - // top and bottom walls - // TODO: Play 'tink' sound - if (_ball.Position.Y - halfHeight < 0) - { - _ball.Position.Y = halfHeight; - _ball.Velocity.Y = -_ball.Velocity.Y; - } - - if (_ball.Position.Y + halfHeight > ScreenHeight) - { - _ball.Position.Y = ScreenHeight - halfHeight; - _ball.Velocity.Y = -_ball.Velocity.Y; - } - - // left and right is out of bounds - // TODO: Play sound and update score - // TODO: Reset ball to default velocity - if (_ball.Position.X > ScreenWidth + halfWidth && _ball.Velocity.X > 0) - { - _ball.Position = new Vector2(ScreenWidth / 2f, ScreenHeight / 2f); - _ball.Velocity = new Vector2(_random.Next(2, 5) * -100, 100); - _leftScore++; - } - - if (_ball.Position.X < -halfWidth && _ball.Velocity.X < 0) - { - _ball.Position = new Vector2(ScreenWidth / 2f, ScreenHeight / 2f); - _ball.Velocity = new Vector2(_random.Next(2, 5) * 100, 100); - _rightScore++; - } - } - - private void ConstrainPaddle(Paddle paddle) - { - if (paddle.BoundingRectangle.Left < 0) - paddle.Position.X = paddle.BoundingRectangle.Width / 2f; - - if (paddle.BoundingRectangle.Right > ScreenWidth) - paddle.Position.X = ScreenWidth - paddle.BoundingRectangle.Width / 2f; - - if (paddle.BoundingRectangle.Top < 0) - paddle.Position.Y = paddle.BoundingRectangle.Height / 2f; - - if (paddle.BoundingRectangle.Bottom > ScreenHeight) - paddle.Position.Y = ScreenHeight - paddle.BoundingRectangle.Height / 2f; - } - - private void MovePaddleAi(Paddle paddle, float elapsedSeconds) - { - const float difficulty = 0.80f; - var paddleSpeed = Math.Abs(_ball.Velocity.Y) * difficulty; - - if (paddleSpeed < 0) - paddleSpeed = -paddleSpeed; - - //ball moving down - if (_ball.Velocity.Y > 0) - { - if (_ball.Position.Y > paddle.Position.Y) - paddle.Position.Y += paddleSpeed * elapsedSeconds; - else - paddle.Position.Y -= paddleSpeed * elapsedSeconds; - } - - //ball moving up - if (_ball.Velocity.Y < 0) - { - if (_ball.Position.Y < paddle.Position.Y) - paddle.Position.Y -= paddleSpeed * elapsedSeconds; - else - paddle.Position.Y += paddleSpeed * elapsedSeconds; - } - } - } -} diff --git a/Source/Demos/Sandbox/Screens/TitleScreen.cs b/Source/Demos/Sandbox/Screens/TitleScreen.cs deleted file mode 100644 index 826b9328..00000000 --- a/Source/Demos/Sandbox/Screens/TitleScreen.cs +++ /dev/null @@ -1,49 +0,0 @@ -using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Graphics; -using Microsoft.Xna.Framework.Input; -using MonoGame.Extended.Input; -using MonoGame.Extended.Screens; -using MonoGame.Extended.Screens.Transitions; - -namespace Sandbox.Screens -{ - public class TitleScreen : GameScreen - { - private SpriteBatch _spriteBatch; - private Texture2D _background; - - public TitleScreen(Game game) - : base(game) - { - game.IsMouseVisible = true; - } - - public override void LoadContent() - { - base.LoadContent(); - _spriteBatch = new SpriteBatch(GraphicsDevice); - _background = Content.Load("title-screen"); - } - - public override void Update(GameTime gameTime) - { - var mouseState = MouseExtended.GetState(); - var keyboardState = KeyboardExtended.GetState(); - - if (keyboardState.WasKeyJustDown(Keys.Escape)) - Game.Exit(); - - if (mouseState.LeftButton == ButtonState.Pressed || keyboardState.WasAnyKeyJustDown()) - ScreenManager.LoadScreen(new PongGameScreen(Game), new FadeTransition(GraphicsDevice, Color.Black, 0.5f)); - } - - public override void Draw(GameTime gameTime) - { - GraphicsDevice.Clear(Color.Magenta); - - _spriteBatch.Begin(samplerState: SamplerState.PointClamp); - _spriteBatch.Draw(_background, new Rectangle(0, 0, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height), Color.White); - _spriteBatch.End(); - } - } -} \ No newline at end of file diff --git a/Source/MonoGame.Extended.Entities/ComponentManager.cs b/Source/MonoGame.Extended.Entities/ComponentManager.cs index cbbca454..c8441be1 100644 --- a/Source/MonoGame.Extended.Entities/ComponentManager.cs +++ b/Source/MonoGame.Extended.Entities/ComponentManager.cs @@ -1,23 +1,49 @@ -using MonoGame.Extended.Collections; +using System; +using System.Collections.Generic; +using Microsoft.Xna.Framework; +using MonoGame.Extended.Collections; +using MonoGame.Extended.Entities.Systems; namespace MonoGame.Extended.Entities { - public class ComponentManager + public class ComponentManager : UpdateSystem { public ComponentManager() { _mappers = new Bag(); + _componentTypes = new Dictionary(); } private readonly Bag _mappers; + private readonly Dictionary _componentTypes; - public void RegisterComponentType() + private ComponentMapper CreateMapperForType() where T : class { - var index = _mappers.Count; - var componentType = new ComponentType(typeof(T), index); - var mapper = new ComponentMapper(); - _mappers[index] = mapper; + var id = _mappers.Count; + var mapper = new ComponentMapper(id); + _mappers[id] = mapper; + return mapper; + } + + public ComponentMapper GetMapper() + where T : class + { + if (_componentTypes.TryGetValue(typeof(T), out var id)) + return _mappers[id] as ComponentMapper; + + var mapper = CreateMapperForType(); + _componentTypes.Add(typeof(T), mapper.Id); + return mapper; + } + + public override void Initialize(ComponentManager componentManager) + { + // TODO : Okay this is weird. + } + + public override void Update(GameTime gameTime) + { } } } \ No newline at end of file diff --git a/Source/MonoGame.Extended.Entities/ComponentMapper.cs b/Source/MonoGame.Extended.Entities/ComponentMapper.cs index 14dc4f88..b8a18ce7 100644 --- a/Source/MonoGame.Extended.Entities/ComponentMapper.cs +++ b/Source/MonoGame.Extended.Entities/ComponentMapper.cs @@ -5,41 +5,49 @@ namespace MonoGame.Extended.Entities { public abstract class ComponentMapper { - protected ComponentMapper(Type componentType) + protected ComponentMapper(int id, Type componentType) { + Id = id; ComponentType = componentType; } + public int Id { get; } public Type ComponentType { get; } } public class ComponentMapper : ComponentMapper where T : class { - public ComponentMapper() - : base(typeof(T)) + public ComponentMapper(int id) + : base(id, typeof(T)) { Components = new Bag(); } + public int Id { get; } public Bag Components { get; } - public void Put(int entityId, T component) + public void CreateComponent(int entityId, T component) { Components[entityId] = component; } - public T Get(int entityId) + public T GetComponent(Entity entity) + { + return GetComponent(entity.Id); + } + + public T GetComponent(int entityId) { return Components[entityId]; } - public bool Has(int entityId) + public bool HasComponent(int entityId) { return Components[entityId] != null; } - public void Delete(int entityId) + public void DeleteComponent(int entityId) { Components[entityId] = null; } diff --git a/Source/MonoGame.Extended.Entities/ComponentType.cs b/Source/MonoGame.Extended.Entities/ComponentType.cs index d0e2b7d0..ebef996b 100644 --- a/Source/MonoGame.Extended.Entities/ComponentType.cs +++ b/Source/MonoGame.Extended.Entities/ComponentType.cs @@ -1,47 +1,46 @@ - -using System; +using System; namespace MonoGame.Extended.Entities { - public class ComponentType : IEquatable - { - public ComponentType(Type type, int index) - { - Type = type; - Index = index; - } + //public class ComponentType : IEquatable + //{ + // public ComponentType(Type type, int id) + // { + // Type = type; + // Id = id; + // } - public Type Type { get; } - public int Index { get; } + // public Type Type { get; } + // public int Id { get; } - public bool Equals(ComponentType other) - { - if (ReferenceEquals(null, other)) return false; - if (ReferenceEquals(this, other)) return true; - return Index == other.Index; - } + // public bool Equals(ComponentType other) + // { + // if (ReferenceEquals(null, other)) return false; + // if (ReferenceEquals(this, other)) return true; + // return Id == other.Id; + // } - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != GetType()) return false; - return Equals((ComponentType) obj); - } + // public override bool Equals(object obj) + // { + // if (ReferenceEquals(null, obj)) return false; + // if (ReferenceEquals(this, obj)) return true; + // if (obj.GetType() != GetType()) return false; + // return Equals((ComponentType) obj); + // } - public override int GetHashCode() - { - return Index; - } + // public override int GetHashCode() + // { + // return Id; + // } - public static bool operator ==(ComponentType left, ComponentType right) - { - return Equals(left, right); - } + // public static bool operator ==(ComponentType left, ComponentType right) + // { + // return Equals(left, right); + // } - public static bool operator !=(ComponentType left, ComponentType right) - { - return !Equals(left, right); - } - } + // public static bool operator !=(ComponentType left, ComponentType right) + // { + // return !Equals(left, right); + // } + //} } diff --git a/Source/MonoGame.Extended.Entities/Entity.cs b/Source/MonoGame.Extended.Entities/Entity.cs new file mode 100644 index 00000000..f5fd05c4 --- /dev/null +++ b/Source/MonoGame.Extended.Entities/Entity.cs @@ -0,0 +1,73 @@ +using System; + +namespace MonoGame.Extended.Entities +{ + public class Entity : IEquatable + { + private readonly ComponentManager _componentManager; + + public Entity(int id, ComponentManager componentManager) + { + Id = id; + _componentManager = componentManager; + } + + public int Id { get; } + + public void Attach(T component) + where T : class + { + var mapper = _componentManager.GetMapper(); + mapper.CreateComponent(Id, component); + } + + public void Detach() + where T : class + { + var mapper = _componentManager.GetMapper(); + mapper.DeleteComponent(Id); + } + + public T Get() + where T : class + { + var mapper = _componentManager.GetMapper(); + return mapper.GetComponent(Id); + } + + public void Destory() + { + throw new NotImplementedException(); + } + + public bool Equals(Entity other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + return Id == other.Id; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != GetType()) return false; + return Equals((Entity) obj); + } + + public override int GetHashCode() + { + return Id; + } + + public static bool operator ==(Entity left, Entity right) + { + return Equals(left, right); + } + + public static bool operator !=(Entity left, Entity right) + { + return !Equals(left, right); + } + } +} \ No newline at end of file diff --git a/Source/MonoGame.Extended.Entities/EntityManager.cs b/Source/MonoGame.Extended.Entities/EntityManager.cs new file mode 100644 index 00000000..1636c0ba --- /dev/null +++ b/Source/MonoGame.Extended.Entities/EntityManager.cs @@ -0,0 +1,37 @@ +using Microsoft.Xna.Framework; +using MonoGame.Extended.Collections; +using MonoGame.Extended.Entities.Systems; + +namespace MonoGame.Extended.Entities +{ + public class EntityManager : UpdateSystem + { + public EntityManager(ComponentManager componentManager) + { + _componentManager = componentManager; + Entities = new Bag(128); + } + + private readonly ComponentManager _componentManager; + private int _nextId; + + public Bag Entities { get; } + + public Entity CreateEntity() + { + // TODO: Recycle dead entites + var id = _nextId++; + var entity = new Entity(id, _componentManager); + Entities[id] = entity; + return entity; + } + + public override void Update(GameTime gameTime) + { + } + + public override void Initialize(ComponentManager componentManager) + { + } + } +} \ No newline at end of file diff --git a/Source/MonoGame.Extended.Entities/EntityWorld.cs b/Source/MonoGame.Extended.Entities/EntityWorld.cs new file mode 100644 index 00000000..3f808bb4 --- /dev/null +++ b/Source/MonoGame.Extended.Entities/EntityWorld.cs @@ -0,0 +1,64 @@ +using System; +using Microsoft.Xna.Framework; +using MonoGame.Extended.Collections; +using MonoGame.Extended.Entities.Systems; + +namespace MonoGame.Extended.Entities +{ + public class EntityWorld : SimpleDrawableGameComponent + { + // TODO: Make these private again + public EntityManager EntityManager { get; } + public ComponentManager ComponentManager { get; } + + private readonly Bag _updateSystems; + private readonly Bag _drawSystems; + + public EntityWorld() + { + ComponentManager = new ComponentManager(); + EntityManager = new EntityManager(ComponentManager); + + _updateSystems = new Bag() + { + ComponentManager, + EntityManager + }; + _drawSystems = new Bag(); + } + + // TODO: Move this to world configuration + public void RegisterSystem(BaseSystem system) + { + switch (system) + { + case DrawSystem drawSystem: + _drawSystems.Add(drawSystem); + break; + case UpdateSystem updateSystem: + _updateSystems.Add(updateSystem); + break; + } + + system.World = this; + system.Initialize(ComponentManager); + } + + public Entity CreateEntity() + { + return EntityManager.CreateEntity(); + } + + public override void Update(GameTime gameTime) + { + foreach (var system in _updateSystems) + system.Update(gameTime); + } + + public override void Draw(GameTime gameTime) + { + foreach (var system in _drawSystems) + system.Draw(gameTime); + } + } +} \ No newline at end of file diff --git a/Source/MonoGame.Extended.Entities/Systems/BaseSystem.cs b/Source/MonoGame.Extended.Entities/Systems/BaseSystem.cs new file mode 100644 index 00000000..2785d2b1 --- /dev/null +++ b/Source/MonoGame.Extended.Entities/Systems/BaseSystem.cs @@ -0,0 +1,8 @@ +namespace MonoGame.Extended.Entities.Systems +{ + public abstract class BaseSystem + { + public EntityWorld World { get; internal set; } + public abstract void Initialize(ComponentManager componentManager); + } +} \ No newline at end of file diff --git a/Source/MonoGame.Extended.Entities/Systems/DrawSystem.cs b/Source/MonoGame.Extended.Entities/Systems/DrawSystem.cs new file mode 100644 index 00000000..517a742b --- /dev/null +++ b/Source/MonoGame.Extended.Entities/Systems/DrawSystem.cs @@ -0,0 +1,13 @@ +using Microsoft.Xna.Framework; + +namespace MonoGame.Extended.Entities.Systems +{ + public abstract class DrawSystem : BaseSystem + { + protected DrawSystem() + { + } + + public abstract void Draw(GameTime gameTime); + } +} \ No newline at end of file diff --git a/Source/MonoGame.Extended.Entities/Systems/UpdateSystem.cs b/Source/MonoGame.Extended.Entities/Systems/UpdateSystem.cs new file mode 100644 index 00000000..c1757c86 --- /dev/null +++ b/Source/MonoGame.Extended.Entities/Systems/UpdateSystem.cs @@ -0,0 +1,13 @@ +using Microsoft.Xna.Framework; + +namespace MonoGame.Extended.Entities.Systems +{ + public abstract class UpdateSystem : BaseSystem + { + protected UpdateSystem() + { + } + + public abstract void Update(GameTime gameTime); + } +} \ No newline at end of file diff --git a/Source/Tests/MonoGame.Extended.Entities.Tests/ComponentMapperTests.cs b/Source/Tests/MonoGame.Extended.Entities.Tests/ComponentMapperTests.cs index ea8007c7..346170e9 100644 --- a/Source/Tests/MonoGame.Extended.Entities.Tests/ComponentMapperTests.cs +++ b/Source/Tests/MonoGame.Extended.Entities.Tests/ComponentMapperTests.cs @@ -1,4 +1,6 @@ -using Xunit; +using System; +using MonoGame.Extended.Entities.Systems; +using Xunit; namespace MonoGame.Extended.Entities.Tests { @@ -8,7 +10,7 @@ namespace MonoGame.Extended.Entities.Tests public void CreateComponentManager() { var manager = new ComponentManager(); - + throw new NotImplementedException(); } } @@ -17,7 +19,7 @@ namespace MonoGame.Extended.Entities.Tests [Fact] public void CreateComponentMapper() { - var mapper = new ComponentMapper(); + var mapper = new ComponentMapper(0); Assert.Equal(typeof(object), mapper.ComponentType); Assert.Empty(mapper.Components); @@ -28,14 +30,14 @@ namespace MonoGame.Extended.Entities.Tests { const int entityId = 3; - var mapper = new ComponentMapper(); + var mapper = new ComponentMapper(1); var component = new Transform2(); - mapper.Put(entityId, component); + mapper.CreateComponent(entityId, component); Assert.Equal(typeof(Transform2), mapper.ComponentType); Assert.True(mapper.Components.Count >= 1); - Assert.Same(component, mapper.Get(entityId)); + Assert.Same(component, mapper.GetComponent(entityId)); } [Fact] @@ -43,13 +45,13 @@ namespace MonoGame.Extended.Entities.Tests { const int entityId = 1; - var mapper = new ComponentMapper(); + var mapper = new ComponentMapper(2); var component = new Transform2(); - mapper.Put(entityId, component); - mapper.Delete(entityId); + mapper.CreateComponent(entityId, component); + mapper.DeleteComponent(entityId); - Assert.False(mapper.Has(entityId)); + Assert.False(mapper.HasComponent(entityId)); } [Fact] @@ -57,14 +59,14 @@ namespace MonoGame.Extended.Entities.Tests { const int entityId = 0; - var mapper = new ComponentMapper(); + var mapper = new ComponentMapper(3); var component = new Transform2(); - Assert.False(mapper.Has(entityId)); + Assert.False(mapper.HasComponent(entityId)); - mapper.Put(entityId, component); + mapper.CreateComponent(entityId, component); - Assert.True(mapper.Has(entityId)); + Assert.True(mapper.HasComponent(entityId)); } } } \ No newline at end of file diff --git a/Source/Tests/MonoGame.Extended.Entities.Tests/ComponentTypeTests.cs b/Source/Tests/MonoGame.Extended.Entities.Tests/ComponentTypeTests.cs index f6b14ccf..89538041 100644 --- a/Source/Tests/MonoGame.Extended.Entities.Tests/ComponentTypeTests.cs +++ b/Source/Tests/MonoGame.Extended.Entities.Tests/ComponentTypeTests.cs @@ -3,18 +3,18 @@ using Xunit; namespace MonoGame.Extended.Entities.Tests { - public class ComponentTypeTests - { - [Fact] - public void CreateComponentType() - { - var type = typeof(Sprite); - var componentType = new ComponentType(type, 3); + //public class ComponentTypeTests + //{ + // [Fact] + // public void CreateComponentType() + // { + // var type = typeof(Sprite); + // var componentType = new ComponentType(type, 3); - Assert.Same(type, componentType.Type); - Assert.Equal(3, componentType.Index); - Assert.Equal(new ComponentType(typeof(Sprite), 3), componentType); - Assert.Equal(componentType.Index, componentType.GetHashCode()); - } - } + // Assert.Same(type, componentType.Type); + // Assert.Equal(3, componentType.Id); + // Assert.Equal(new ComponentType(typeof(Sprite), 3), componentType); + // Assert.Equal(componentType.Id, componentType.GetHashCode()); + // } + //} } \ No newline at end of file