diff --git a/Source/Demos/Platformer/AutofacDependencyResolver.cs b/Source/Demos/Platformer/AutofacDependencyResolver.cs
index 15d3eba3..8fba167a 100644
--- a/Source/Demos/Platformer/AutofacDependencyResolver.cs
+++ b/Source/Demos/Platformer/AutofacDependencyResolver.cs
@@ -2,6 +2,7 @@
using System.Linq;
using Autofac;
using MonoGame.Extended.Entities;
+using MonoGame.Extended.Entities.Legacy;
namespace Platformer
{
diff --git a/Source/Demos/Platformer/EntityFactory.cs b/Source/Demos/Platformer/EntityFactory.cs
index 42243789..db2caa11 100644
--- a/Source/Demos/Platformer/EntityFactory.cs
+++ b/Source/Demos/Platformer/EntityFactory.cs
@@ -5,6 +5,7 @@ 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;
using Platformer.Components;
diff --git a/Source/Demos/Platformer/GameBase.cs b/Source/Demos/Platformer/GameBase.cs
index 97e653ef..a29d9e81 100644
--- a/Source/Demos/Platformer/GameBase.cs
+++ b/Source/Demos/Platformer/GameBase.cs
@@ -2,6 +2,7 @@
using Autofac;
using Microsoft.Xna.Framework;
using MonoGame.Extended.Entities;
+using MonoGame.Extended.Entities.Legacy;
namespace Platformer
{
diff --git a/Source/Demos/Platformer/GameMain.cs b/Source/Demos/Platformer/GameMain.cs
index 2c7f8608..35db88ac 100644
--- a/Source/Demos/Platformer/GameMain.cs
+++ b/Source/Demos/Platformer/GameMain.cs
@@ -3,6 +3,7 @@ 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;
using Platformer.Systems;
diff --git a/Source/Demos/Platformer/Systems/PlayerSystem.cs b/Source/Demos/Platformer/Systems/PlayerSystem.cs
index a7878123..a80811f7 100644
--- a/Source/Demos/Platformer/Systems/PlayerSystem.cs
+++ b/Source/Demos/Platformer/Systems/PlayerSystem.cs
@@ -5,6 +5,7 @@ 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;
using Platformer.Components;
diff --git a/Source/Demos/Platformer/Systems/RenderSystem.cs b/Source/Demos/Platformer/Systems/RenderSystem.cs
index 25683bb9..a76f7d55 100644
--- a/Source/Demos/Platformer/Systems/RenderSystem.cs
+++ b/Source/Demos/Platformer/Systems/RenderSystem.cs
@@ -3,6 +3,7 @@ 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;
namespace Platformer.Systems
diff --git a/Source/Demos/Platformer/Systems/WorldSystem.cs b/Source/Demos/Platformer/Systems/WorldSystem.cs
index c7efdfb5..faa0189a 100644
--- a/Source/Demos/Platformer/Systems/WorldSystem.cs
+++ b/Source/Demos/Platformer/Systems/WorldSystem.cs
@@ -1,6 +1,7 @@
using Microsoft.Xna.Framework;
using MonoGame.Extended;
using MonoGame.Extended.Entities;
+using MonoGame.Extended.Entities.Legacy;
using Platformer.Collisions;
namespace Platformer.Systems
diff --git a/Source/Demos/Sandbox/Content/Content.mgcb b/Source/Demos/Sandbox/Content/Content.mgcb
new file mode 100644
index 00000000..3b1872f9
--- /dev/null
+++ b/Source/Demos/Sandbox/Content/Content.mgcb
@@ -0,0 +1,99 @@
+
+#----------------------------- Global Properties ----------------------------#
+
+/outputDir:bin/$(Platform)
+/intermediateDir:obj/$(Platform)
+/platform:DesktopGL
+/config:
+/profile:Reach
+/compress:False
+
+#-------------------------------- References --------------------------------#
+
+/reference:..\..\..\MonoGame.Extended.Content.Pipeline\bin\netstandard2.0\MonoGame.Extended.Content.Pipeline.dll
+
+#---------------------------------- Content ---------------------------------#
+
+#begin ballGrey.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: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
+/build:kenney-rocket-square.fnt
+
+#begin kenney-rocket-square_0.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: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/ballGrey.png b/Source/Demos/Sandbox/Content/ballGrey.png
new file mode 100644
index 00000000..c2d8aaa9
Binary files /dev/null and b/Source/Demos/Sandbox/Content/ballGrey.png differ
diff --git a/Source/Demos/Sandbox/Content/court.png b/Source/Demos/Sandbox/Content/court.png
new file mode 100644
index 00000000..06f4a523
Binary files /dev/null and b/Source/Demos/Sandbox/Content/court.png differ
diff --git a/Source/Demos/Sandbox/Content/kenney-rocket-square.bmfc b/Source/Demos/Sandbox/Content/kenney-rocket-square.bmfc
new file mode 100644
index 00000000..7111a374
--- /dev/null
+++ b/Source/Demos/Sandbox/Content/kenney-rocket-square.bmfc
@@ -0,0 +1,55 @@
+# AngelCode Bitmap Font Generator configuration file
+fileVersion=1
+
+# font settings
+fontName=Kenney Rocket Square
+fontFile=
+charSet=0
+fontSize=32
+aa=1
+scaleH=100
+useSmoothing=0
+isBold=0
+isItalic=0
+useUnicode=1
+disableBoxChars=1
+outputInvalidCharGlyph=0
+dontIncludeKerningPairs=0
+useHinting=1
+renderFromOutline=0
+useClearType=0
+
+# character alignment
+paddingDown=0
+paddingUp=0
+paddingRight=0
+paddingLeft=0
+spacingHoriz=1
+spacingVert=1
+useFixedHeight=0
+forceZero=0
+
+# output file
+outWidth=256
+outHeight=256
+outBitDepth=32
+fontDescFormat=1
+fourChnlPacked=0
+textureFormat=png
+textureCompression=0
+alphaChnl=0
+redChnl=4
+greenChnl=4
+blueChnl=4
+invA=0
+invR=0
+invG=0
+invB=0
+
+# outline
+outlineThickness=1
+
+# selected chars
+chars=32-126
+
+# imported icon images
diff --git a/Source/Demos/Sandbox/Content/kenney-rocket-square.fnt b/Source/Demos/Sandbox/Content/kenney-rocket-square.fnt
new file mode 100644
index 00000000..213ce1be
--- /dev/null
+++ b/Source/Demos/Sandbox/Content/kenney-rocket-square.fnt
@@ -0,0 +1,105 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Source/Demos/Sandbox/Content/kenney-rocket-square_0.png b/Source/Demos/Sandbox/Content/kenney-rocket-square_0.png
new file mode 100644
index 00000000..596c7366
Binary files /dev/null and b/Source/Demos/Sandbox/Content/kenney-rocket-square_0.png differ
diff --git a/Source/Demos/Sandbox/Content/paddleBlue.png b/Source/Demos/Sandbox/Content/paddleBlue.png
new file mode 100644
index 00000000..132cef3f
Binary files /dev/null and b/Source/Demos/Sandbox/Content/paddleBlue.png differ
diff --git a/Source/Demos/Sandbox/Content/paddleRed.png b/Source/Demos/Sandbox/Content/paddleRed.png
new file mode 100644
index 00000000..f51f1985
Binary files /dev/null and b/Source/Demos/Sandbox/Content/paddleRed.png differ
diff --git a/Source/Demos/Sandbox/Content/pip.wav b/Source/Demos/Sandbox/Content/pip.wav
new file mode 100644
index 00000000..ee26c6d5
Binary files /dev/null and b/Source/Demos/Sandbox/Content/pip.wav differ
diff --git a/Source/Demos/Sandbox/Content/title-screen.png b/Source/Demos/Sandbox/Content/title-screen.png
new file mode 100644
index 00000000..cdf228a0
Binary files /dev/null and b/Source/Demos/Sandbox/Content/title-screen.png differ
diff --git a/Source/Demos/Sandbox/GameMain.cs b/Source/Demos/Sandbox/GameMain.cs
new file mode 100644
index 00000000..2d602193
--- /dev/null
+++ b/Source/Demos/Sandbox/GameMain.cs
@@ -0,0 +1,156 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using Microsoft.Xna.Framework;
+using MonoGame.Extended;
+using MonoGame.Extended.Screens;
+using MonoGame.Extended.Screens.Transitions;
+using Sandbox.Screens;
+
+namespace Sandbox
+{
+ public class EcsAspect
+ {
+ private readonly BitArray _allSet;
+ private readonly BitArray _exclusionSet;
+ private readonly BitArray _oneSet;
+
+ private const int _defaultSize = 32;
+
+ public EcsAspect()
+ {
+ _allSet = new BitArray(_defaultSize);
+ _exclusionSet = new BitArray(_defaultSize);
+ _oneSet = new BitArray(_defaultSize);
+ }
+
+ public void All(bool[] set)
+ {
+ 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);
+ }
+
+ public override void Draw(GameTime gameTime)
+ {
+ foreach (var system in _systems)
+ system.Draw(gameTime);
+ }
+ }
+
+ public class GameMain : Game
+ {
+ // ReSharper disable once NotAccessedField.Local
+ private readonly GraphicsDeviceManager _graphics;
+ private readonly ScreenManager _screenManager;
+
+ public GameMain()
+ {
+ _graphics = new GraphicsDeviceManager(this)
+ {
+ PreferredBackBufferWidth = 800,
+ PreferredBackBufferHeight = 480,
+ SynchronizeWithVerticalRetrace = false
+ };
+
+ Content.RootDirectory = "Content";
+ IsFixedTimeStep = true;
+ TargetElapsedTime = TimeSpan.FromSeconds(1f / 60f);
+
+ _screenManager = Components.Add();
+ }
+
+ protected override void LoadContent()
+ {
+ base.LoadContent();
+
+ _screenManager.LoadScreen(new TitleScreen(this), new FadeTransition(GraphicsDevice, Color.Black, 0.5f));
+ }
+ }
+}
diff --git a/Source/Demos/Sandbox/GameObjects/Ball.cs b/Source/Demos/Sandbox/GameObjects/Ball.cs
new file mode 100644
index 00000000..d0016b0b
--- /dev/null
+++ b/Source/Demos/Sandbox/GameObjects/Ball.cs
@@ -0,0 +1,9 @@
+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
new file mode 100644
index 00000000..204932e9
--- /dev/null
+++ b/Source/Demos/Sandbox/GameObjects/GameObject.cs
@@ -0,0 +1,15 @@
+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
new file mode 100644
index 00000000..d59a641b
--- /dev/null
+++ b/Source/Demos/Sandbox/GameObjects/Paddle.cs
@@ -0,0 +1,6 @@
+namespace Sandbox.GameObjects
+{
+ public class Paddle : GameObject
+ {
+ }
+}
\ No newline at end of file
diff --git a/Source/Demos/Sandbox/Icon.bmp b/Source/Demos/Sandbox/Icon.bmp
new file mode 100644
index 00000000..2b481653
Binary files /dev/null and b/Source/Demos/Sandbox/Icon.bmp differ
diff --git a/Source/Demos/Sandbox/Icon.ico b/Source/Demos/Sandbox/Icon.ico
new file mode 100644
index 00000000..7d9dec18
Binary files /dev/null and b/Source/Demos/Sandbox/Icon.ico differ
diff --git a/Source/Demos/Sandbox/Program.cs b/Source/Demos/Sandbox/Program.cs
new file mode 100644
index 00000000..e4bb48f1
--- /dev/null
+++ b/Source/Demos/Sandbox/Program.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Sandbox
+{
+ public static class Program
+ {
+ [STAThread]
+ private static void Main()
+ {
+ using (var game = new GameMain())
+ game.Run();
+ }
+ }
+}
diff --git a/Source/Demos/Sandbox/Sandbox.csproj b/Source/Demos/Sandbox/Sandbox.csproj
new file mode 100644
index 00000000..30f19912
--- /dev/null
+++ b/Source/Demos/Sandbox/Sandbox.csproj
@@ -0,0 +1,21 @@
+
+
+ WinExe
+ netcoreapp2.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Source/Demos/Sandbox/Screens/PongGameScreen.cs b/Source/Demos/Sandbox/Screens/PongGameScreen.cs
new file mode 100644
index 00000000..f6cbd7c6
--- /dev/null
+++ b/Source/Demos/Sandbox/Screens/PongGameScreen.cs
@@ -0,0 +1,240 @@
+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
new file mode 100644
index 00000000..826b9328
--- /dev/null
+++ b/Source/Demos/Sandbox/Screens/TitleScreen.cs
@@ -0,0 +1,49 @@
+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/Demos/Sandbox/app.manifest b/Source/Demos/Sandbox/app.manifest
new file mode 100644
index 00000000..0acf5bcd
--- /dev/null
+++ b/Source/Demos/Sandbox/app.manifest
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true/pm
+
+
+
+
diff --git a/Source/MonoGame.Extended.Entities/ComponentManager.cs b/Source/MonoGame.Extended.Entities/ComponentManager.cs
new file mode 100644
index 00000000..cbbca454
--- /dev/null
+++ b/Source/MonoGame.Extended.Entities/ComponentManager.cs
@@ -0,0 +1,23 @@
+using MonoGame.Extended.Collections;
+
+namespace MonoGame.Extended.Entities
+{
+ public class ComponentManager
+ {
+ public ComponentManager()
+ {
+ _mappers = new Bag();
+ }
+
+ private readonly Bag _mappers;
+
+ public void RegisterComponentType()
+ where T : class
+ {
+ var index = _mappers.Count;
+ var componentType = new ComponentType(typeof(T), index);
+ var mapper = new ComponentMapper();
+ _mappers[index] = mapper;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Source/MonoGame.Extended.Entities/ComponentMapper.cs b/Source/MonoGame.Extended.Entities/ComponentMapper.cs
new file mode 100644
index 00000000..14dc4f88
--- /dev/null
+++ b/Source/MonoGame.Extended.Entities/ComponentMapper.cs
@@ -0,0 +1,47 @@
+using System;
+using MonoGame.Extended.Collections;
+
+namespace MonoGame.Extended.Entities
+{
+ public abstract class ComponentMapper
+ {
+ protected ComponentMapper(Type componentType)
+ {
+ ComponentType = componentType;
+ }
+
+ public Type ComponentType { get; }
+ }
+
+ public class ComponentMapper : ComponentMapper
+ where T : class
+ {
+ public ComponentMapper()
+ : base(typeof(T))
+ {
+ Components = new Bag();
+ }
+
+ public Bag Components { get; }
+
+ public void Put(int entityId, T component)
+ {
+ Components[entityId] = component;
+ }
+
+ public T Get(int entityId)
+ {
+ return Components[entityId];
+ }
+
+ public bool Has(int entityId)
+ {
+ return Components[entityId] != null;
+ }
+
+ public void Delete(int entityId)
+ {
+ Components[entityId] = null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Source/MonoGame.Extended.Entities/ComponentType.cs b/Source/MonoGame.Extended.Entities/ComponentType.cs
new file mode 100644
index 00000000..d0e2b7d0
--- /dev/null
+++ b/Source/MonoGame.Extended.Entities/ComponentType.cs
@@ -0,0 +1,47 @@
+
+using System;
+
+namespace MonoGame.Extended.Entities
+{
+ public class ComponentType : IEquatable
+ {
+ public ComponentType(Type type, int index)
+ {
+ Type = type;
+ Index = index;
+ }
+
+ public Type Type { get; }
+ public int Index { get; }
+
+ public bool Equals(ComponentType other)
+ {
+ if (ReferenceEquals(null, other)) return false;
+ if (ReferenceEquals(this, other)) return true;
+ return Index == other.Index;
+ }
+
+ 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 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/Aspect.cs b/Source/MonoGame.Extended.Entities/Legacy/Aspect.cs
similarity index 96%
rename from Source/MonoGame.Extended.Entities/Aspect.cs
rename to Source/MonoGame.Extended.Entities/Legacy/Aspect.cs
index 9ff553b4..cb229720 100644
--- a/Source/MonoGame.Extended.Entities/Aspect.cs
+++ b/Source/MonoGame.Extended.Entities/Legacy/Aspect.cs
@@ -34,11 +34,9 @@
//
// --------------------------------------------------------------------------------------------------------------------
-using System.Linq.Expressions;
-
-namespace MonoGame.Extended.Entities
+namespace MonoGame.Extended.Entities.Legacy
{
- internal class Aspect
+ public class Aspect
{
// match entities with components using boolean logic:
// (A and B and C and ..) AND (D or E or F or ...) AND NOT(G or H or I or ..)
@@ -87,7 +85,7 @@ namespace MonoGame.Extended.Entities
NorMask = new BitVector(norMask);
}
- internal bool Matches(BitVector componentBits)
+ public bool Matches(BitVector componentBits)
{
AndMask.And(componentBits, ref Result);
if (!Result.Equals(AndMask))
diff --git a/Source/MonoGame.Extended.Entities/AspectAttribute.cs b/Source/MonoGame.Extended.Entities/Legacy/AspectAttribute.cs
similarity index 91%
rename from Source/MonoGame.Extended.Entities/AspectAttribute.cs
rename to Source/MonoGame.Extended.Entities/Legacy/AspectAttribute.cs
index 467ccbdb..eb90bb3f 100644
--- a/Source/MonoGame.Extended.Entities/AspectAttribute.cs
+++ b/Source/MonoGame.Extended.Entities/Legacy/AspectAttribute.cs
@@ -1,6 +1,6 @@
using System;
-namespace MonoGame.Extended.Entities
+namespace MonoGame.Extended.Entities.Legacy
{
public enum AspectType
{
diff --git a/Source/MonoGame.Extended.Entities/BitVector.cs b/Source/MonoGame.Extended.Entities/Legacy/BitVector.cs
similarity index 98%
rename from Source/MonoGame.Extended.Entities/BitVector.cs
rename to Source/MonoGame.Extended.Entities/Legacy/BitVector.cs
index 8eb43691..b24d6f8f 100644
--- a/Source/MonoGame.Extended.Entities/BitVector.cs
+++ b/Source/MonoGame.Extended.Entities/Legacy/BitVector.cs
@@ -49,9 +49,9 @@ SOFTWARE.
using System;
-namespace MonoGame.Extended.Entities
+namespace MonoGame.Extended.Entities.Legacy
{
- internal sealed class BitVector
+ public sealed class BitVector
{
// XPerY=n means that n Xs can be stored in 1 Y.
private const int _bitsPerInt32 = 32;
diff --git a/Source/MonoGame.Extended.Entities/DefaultDependencyResolver.cs b/Source/MonoGame.Extended.Entities/Legacy/DefaultDependencyResolver.cs
similarity index 87%
rename from Source/MonoGame.Extended.Entities/DefaultDependencyResolver.cs
rename to Source/MonoGame.Extended.Entities/Legacy/DefaultDependencyResolver.cs
index e7b46b1f..50ef786c 100644
--- a/Source/MonoGame.Extended.Entities/DefaultDependencyResolver.cs
+++ b/Source/MonoGame.Extended.Entities/Legacy/DefaultDependencyResolver.cs
@@ -1,6 +1,6 @@
using System;
-namespace MonoGame.Extended.Entities
+namespace MonoGame.Extended.Entities.Legacy
{
public class DefaultDependencyResolver : DependencyResolver
{
diff --git a/Source/MonoGame.Extended.Entities/DependencyResolver.cs b/Source/MonoGame.Extended.Entities/Legacy/DependencyResolver.cs
similarity index 86%
rename from Source/MonoGame.Extended.Entities/DependencyResolver.cs
rename to Source/MonoGame.Extended.Entities/Legacy/DependencyResolver.cs
index aba9dd95..a4a3be91 100644
--- a/Source/MonoGame.Extended.Entities/DependencyResolver.cs
+++ b/Source/MonoGame.Extended.Entities/Legacy/DependencyResolver.cs
@@ -1,6 +1,6 @@
using System;
-namespace MonoGame.Extended.Entities
+namespace MonoGame.Extended.Entities.Legacy
{
public abstract class DependencyResolver
{
diff --git a/Source/MonoGame.Extended.Entities/Entity.cs b/Source/MonoGame.Extended.Entities/Legacy/Entity.cs
similarity index 99%
rename from Source/MonoGame.Extended.Entities/Entity.cs
rename to Source/MonoGame.Extended.Entities/Legacy/Entity.cs
index db4f562c..d428e22e 100644
--- a/Source/MonoGame.Extended.Entities/Entity.cs
+++ b/Source/MonoGame.Extended.Entities/Legacy/Entity.cs
@@ -37,9 +37,10 @@
using System;
using System.Runtime.CompilerServices;
using MonoGame.Extended.Collections;
+
// ReSharper disable InconsistentNaming
-namespace MonoGame.Extended.Entities
+namespace MonoGame.Extended.Entities.Legacy
{
public sealed class Entity : IPoolable
{
diff --git a/Source/MonoGame.Extended.Entities/EntityComponentDelegate.cs b/Source/MonoGame.Extended.Entities/Legacy/EntityComponentDelegate.cs
similarity index 66%
rename from Source/MonoGame.Extended.Entities/EntityComponentDelegate.cs
rename to Source/MonoGame.Extended.Entities/Legacy/EntityComponentDelegate.cs
index f1c893ae..4df6aa41 100644
--- a/Source/MonoGame.Extended.Entities/EntityComponentDelegate.cs
+++ b/Source/MonoGame.Extended.Entities/Legacy/EntityComponentDelegate.cs
@@ -1,4 +1,4 @@
-namespace MonoGame.Extended.Entities
+namespace MonoGame.Extended.Entities.Legacy
{
public delegate void EntityComponentDelegate(Entity entity, object component);
}
\ No newline at end of file
diff --git a/Source/MonoGame.Extended.Entities/EntityComponentPool.cs b/Source/MonoGame.Extended.Entities/Legacy/EntityComponentPool.cs
similarity index 93%
rename from Source/MonoGame.Extended.Entities/EntityComponentPool.cs
rename to Source/MonoGame.Extended.Entities/Legacy/EntityComponentPool.cs
index 4ff1c853..fac8073a 100644
--- a/Source/MonoGame.Extended.Entities/EntityComponentPool.cs
+++ b/Source/MonoGame.Extended.Entities/Legacy/EntityComponentPool.cs
@@ -1,6 +1,6 @@
using MonoGame.Extended.Collections;
-namespace MonoGame.Extended.Entities
+namespace MonoGame.Extended.Entities.Legacy
{
internal interface IComponentPool
{
diff --git a/Source/MonoGame.Extended.Entities/EntityComponentPoolAttribute.cs b/Source/MonoGame.Extended.Entities/Legacy/EntityComponentPoolAttribute.cs
similarity index 98%
rename from Source/MonoGame.Extended.Entities/EntityComponentPoolAttribute.cs
rename to Source/MonoGame.Extended.Entities/Legacy/EntityComponentPoolAttribute.cs
index 8b0376b4..08652c7d 100644
--- a/Source/MonoGame.Extended.Entities/EntityComponentPoolAttribute.cs
+++ b/Source/MonoGame.Extended.Entities/Legacy/EntityComponentPoolAttribute.cs
@@ -37,7 +37,7 @@
using System;
using MonoGame.Extended.Collections;
-namespace MonoGame.Extended.Entities
+namespace MonoGame.Extended.Entities.Legacy
{
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
public sealed class EntityComponentPoolAttribute : Attribute
diff --git a/Source/MonoGame.Extended.Entities/EntityComponentSystem.cs b/Source/MonoGame.Extended.Entities/Legacy/EntityComponentSystem.cs
similarity index 98%
rename from Source/MonoGame.Extended.Entities/EntityComponentSystem.cs
rename to Source/MonoGame.Extended.Entities/Legacy/EntityComponentSystem.cs
index c33a4262..d5e9ab9c 100644
--- a/Source/MonoGame.Extended.Entities/EntityComponentSystem.cs
+++ b/Source/MonoGame.Extended.Entities/Legacy/EntityComponentSystem.cs
@@ -37,7 +37,7 @@ using Microsoft.Xna.Framework;
using MonoGame.Extended.Animations;
using MonoGame.Extended.Sprites;
-namespace MonoGame.Extended.Entities
+namespace MonoGame.Extended.Entities.Legacy
{
public sealed class EntityComponentSystem : DrawableGameComponent
{
@@ -211,9 +211,8 @@ namespace MonoGame.Extended.Entities
return;
var processingSystem = _dependencyResolver.Resolve(typeInfo.AsType());
- var entityProcessingSystem = processingSystem as EntityProcessingSystem;
- if (entityProcessingSystem != null)
+ if (processingSystem is EntityProcessingSystem entityProcessingSystem)
entityProcessingSystem.Aspect = new Aspect(andMask, orMask, norMask);
_systemManager.AddSystem(processingSystem, systemAttribute.GameLoopType, systemAttribute.Layer, SystemExecutionType.Synchronous);
diff --git a/Source/MonoGame.Extended.Entities/EntityComponentType.cs b/Source/MonoGame.Extended.Entities/Legacy/EntityComponentType.cs
similarity index 98%
rename from Source/MonoGame.Extended.Entities/EntityComponentType.cs
rename to Source/MonoGame.Extended.Entities/Legacy/EntityComponentType.cs
index c6922a07..0c7181db 100644
--- a/Source/MonoGame.Extended.Entities/EntityComponentType.cs
+++ b/Source/MonoGame.Extended.Entities/Legacy/EntityComponentType.cs
@@ -37,7 +37,7 @@
using System;
using System.Diagnostics;
-namespace MonoGame.Extended.Entities
+namespace MonoGame.Extended.Entities.Legacy
{
[DebuggerDisplay("Index:{" + nameof(Index) + "}")]
public sealed class EntityComponentType
diff --git a/Source/MonoGame.Extended.Entities/EntityDelegate.cs b/Source/MonoGame.Extended.Entities/Legacy/EntityDelegate.cs
similarity index 57%
rename from Source/MonoGame.Extended.Entities/EntityDelegate.cs
rename to Source/MonoGame.Extended.Entities/Legacy/EntityDelegate.cs
index 21cb76b3..ec270b54 100644
--- a/Source/MonoGame.Extended.Entities/EntityDelegate.cs
+++ b/Source/MonoGame.Extended.Entities/Legacy/EntityDelegate.cs
@@ -1,4 +1,4 @@
-namespace MonoGame.Extended.Entities
+namespace MonoGame.Extended.Entities.Legacy
{
public delegate void EntityDelegate(Entity entity);
}
\ No newline at end of file
diff --git a/Source/MonoGame.Extended.Entities/EntityManager.cs b/Source/MonoGame.Extended.Entities/Legacy/EntityManager.cs
similarity index 99%
rename from Source/MonoGame.Extended.Entities/EntityManager.cs
rename to Source/MonoGame.Extended.Entities/Legacy/EntityManager.cs
index f2f30d37..b9dff309 100644
--- a/Source/MonoGame.Extended.Entities/EntityManager.cs
+++ b/Source/MonoGame.Extended.Entities/Legacy/EntityManager.cs
@@ -40,7 +40,7 @@ using System.Diagnostics;
using System.Reflection;
using MonoGame.Extended.Collections;
-namespace MonoGame.Extended.Entities
+namespace MonoGame.Extended.Entities.Legacy
{
public class EntityManager
{
diff --git a/Source/MonoGame.Extended.Entities/EntityProcessingSystem.cs b/Source/MonoGame.Extended.Entities/Legacy/EntityProcessingSystem.cs
similarity index 99%
rename from Source/MonoGame.Extended.Entities/EntityProcessingSystem.cs
rename to Source/MonoGame.Extended.Entities/Legacy/EntityProcessingSystem.cs
index 6c590576..e47740ff 100644
--- a/Source/MonoGame.Extended.Entities/EntityProcessingSystem.cs
+++ b/Source/MonoGame.Extended.Entities/Legacy/EntityProcessingSystem.cs
@@ -37,7 +37,7 @@
using System.Collections.Generic;
using Microsoft.Xna.Framework;
-namespace MonoGame.Extended.Entities
+namespace MonoGame.Extended.Entities.Legacy
{
public abstract class EntityProcessingSystem : ProcessingSystem
{
diff --git a/Source/MonoGame.Extended.Entities/EntitySystemAttribute.cs b/Source/MonoGame.Extended.Entities/Legacy/EntitySystemAttribute.cs
similarity index 98%
rename from Source/MonoGame.Extended.Entities/EntitySystemAttribute.cs
rename to Source/MonoGame.Extended.Entities/Legacy/EntitySystemAttribute.cs
index 2a405a7c..f5892738 100644
--- a/Source/MonoGame.Extended.Entities/EntitySystemAttribute.cs
+++ b/Source/MonoGame.Extended.Entities/Legacy/EntitySystemAttribute.cs
@@ -36,7 +36,7 @@
using System;
-namespace MonoGame.Extended.Entities
+namespace MonoGame.Extended.Entities.Legacy
{
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
public sealed class EntitySystemAttribute : Attribute
diff --git a/Source/MonoGame.Extended.Entities/EntityTemplate.cs b/Source/MonoGame.Extended.Entities/Legacy/EntityTemplate.cs
similarity index 98%
rename from Source/MonoGame.Extended.Entities/EntityTemplate.cs
rename to Source/MonoGame.Extended.Entities/Legacy/EntityTemplate.cs
index 58299061..1660e95c 100644
--- a/Source/MonoGame.Extended.Entities/EntityTemplate.cs
+++ b/Source/MonoGame.Extended.Entities/Legacy/EntityTemplate.cs
@@ -34,7 +34,7 @@
//
// --------------------------------------------------------------------------------------------------------------------
-namespace MonoGame.Extended.Entities
+namespace MonoGame.Extended.Entities.Legacy
{
public abstract class EntityTemplate
{
diff --git a/Source/MonoGame.Extended.Entities/EntityTemplateAttribute.cs b/Source/MonoGame.Extended.Entities/Legacy/EntityTemplateAttribute.cs
similarity index 98%
rename from Source/MonoGame.Extended.Entities/EntityTemplateAttribute.cs
rename to Source/MonoGame.Extended.Entities/Legacy/EntityTemplateAttribute.cs
index 07da8b05..e2c4f052 100644
--- a/Source/MonoGame.Extended.Entities/EntityTemplateAttribute.cs
+++ b/Source/MonoGame.Extended.Entities/Legacy/EntityTemplateAttribute.cs
@@ -36,7 +36,7 @@
using System;
-namespace MonoGame.Extended.Entities
+namespace MonoGame.Extended.Entities.Legacy
{
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
public sealed class EntityTemplateAttribute : Attribute
diff --git a/Source/MonoGame.Extended.Entities/PoolableComponent.cs b/Source/MonoGame.Extended.Entities/Legacy/PoolableComponent.cs
similarity index 98%
rename from Source/MonoGame.Extended.Entities/PoolableComponent.cs
rename to Source/MonoGame.Extended.Entities/Legacy/PoolableComponent.cs
index 44876f42..cf68579d 100644
--- a/Source/MonoGame.Extended.Entities/PoolableComponent.cs
+++ b/Source/MonoGame.Extended.Entities/Legacy/PoolableComponent.cs
@@ -36,7 +36,7 @@
using MonoGame.Extended.Collections;
-namespace MonoGame.Extended.Entities
+namespace MonoGame.Extended.Entities.Legacy
{
public abstract class PoolableComponent : IPoolable
{
diff --git a/Source/MonoGame.Extended.Entities/ProcessingSystem.cs b/Source/MonoGame.Extended.Entities/Legacy/ProcessingSystem.cs
similarity index 98%
rename from Source/MonoGame.Extended.Entities/ProcessingSystem.cs
rename to Source/MonoGame.Extended.Entities/Legacy/ProcessingSystem.cs
index 49d615f1..3e0061af 100644
--- a/Source/MonoGame.Extended.Entities/ProcessingSystem.cs
+++ b/Source/MonoGame.Extended.Entities/Legacy/ProcessingSystem.cs
@@ -38,7 +38,7 @@ using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
-namespace MonoGame.Extended.Entities
+namespace MonoGame.Extended.Entities.Legacy
{
public abstract class ProcessingSystem
{
diff --git a/Source/MonoGame.Extended.Entities/SystemManager.cs b/Source/MonoGame.Extended.Entities/Legacy/SystemManager.cs
similarity index 98%
rename from Source/MonoGame.Extended.Entities/SystemManager.cs
rename to Source/MonoGame.Extended.Entities/Legacy/SystemManager.cs
index c15ffd69..b53f4bda 100644
--- a/Source/MonoGame.Extended.Entities/SystemManager.cs
+++ b/Source/MonoGame.Extended.Entities/Legacy/SystemManager.cs
@@ -40,7 +40,7 @@ using System.Diagnostics;
using Microsoft.Xna.Framework;
using MonoGame.Extended.Collections;
-namespace MonoGame.Extended.Entities
+namespace MonoGame.Extended.Entities.Legacy
{
public enum GameLoopType
{
@@ -149,10 +149,8 @@ namespace MonoGame.Extended.Entities
system.EntityComponentSystem = _manager;
Systems.Add(system);
-
-
- var processingSystem = system as EntityProcessingSystem;
- if (processingSystem != null)
+
+ if (system is EntityProcessingSystem processingSystem)
{
processingSystem.Index = ProcessingSystems.Count;
ProcessingSystems.Add(processingSystem);
diff --git a/Source/MonoGame.Extended.sln b/Source/MonoGame.Extended.sln
index a8fffb61..b2a703a1 100644
--- a/Source/MonoGame.Extended.sln
+++ b/Source/MonoGame.Extended.sln
@@ -97,6 +97,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Gui", "Demos\Gui\Gui.csproj
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoGame.Extended.Collisions.Tests", "Tests\MonoGame.Extended.Collisions.Tests\MonoGame.Extended.Collisions.Tests.csproj", "{CB439E84-F0F6-4790-8CD1-8A66C3D7B4DA}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sandbox", "Demos\Sandbox\Sandbox.csproj", "{778B49B7-CA0E-4BC5-82EA-326E8019379C}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -297,6 +299,14 @@ Global
{CB439E84-F0F6-4790-8CD1-8A66C3D7B4DA}.Release|Any CPU.Build.0 = Release|Any CPU
{CB439E84-F0F6-4790-8CD1-8A66C3D7B4DA}.Release|x86.ActiveCfg = Release|Any CPU
{CB439E84-F0F6-4790-8CD1-8A66C3D7B4DA}.Release|x86.Build.0 = Release|Any CPU
+ {778B49B7-CA0E-4BC5-82EA-326E8019379C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {778B49B7-CA0E-4BC5-82EA-326E8019379C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {778B49B7-CA0E-4BC5-82EA-326E8019379C}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {778B49B7-CA0E-4BC5-82EA-326E8019379C}.Debug|x86.Build.0 = Debug|Any CPU
+ {778B49B7-CA0E-4BC5-82EA-326E8019379C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {778B49B7-CA0E-4BC5-82EA-326E8019379C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {778B49B7-CA0E-4BC5-82EA-326E8019379C}.Release|x86.ActiveCfg = Release|Any CPU
+ {778B49B7-CA0E-4BC5-82EA-326E8019379C}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -314,6 +324,7 @@ Global
{34841DEB-EEC0-477C-B19D-CBB6DF49ED39} = {E5A148A1-DE7B-4D17-ABE8-831B9673B863}
{8AC0C265-E986-4AB1-8FF7-4A0582695B0D} = {932F8931-4A8D-4205-BFCF-98E794207786}
{CB439E84-F0F6-4790-8CD1-8A66C3D7B4DA} = {E5A148A1-DE7B-4D17-ABE8-831B9673B863}
+ {778B49B7-CA0E-4BC5-82EA-326E8019379C} = {932F8931-4A8D-4205-BFCF-98E794207786}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {8ED5A62D-25EC-4331-9F99-BDD1E10C02A0}
diff --git a/Source/MonoGame.Extended/Collections/Bag.cs b/Source/MonoGame.Extended/Collections/Bag.cs
index bd5967ca..64e03ba3 100644
--- a/Source/MonoGame.Extended/Collections/Bag.cs
+++ b/Source/MonoGame.Extended/Collections/Bag.cs
@@ -55,7 +55,7 @@ namespace MonoGame.Extended.Collections
public T this[int index]
{
- get { return _items[index]; }
+ get => _items[index];
set
{
EnsureCapacity(index + 1);
diff --git a/Source/Tests/MonoGame.Extended.Entities.Tests/ComponentMapperTests.cs b/Source/Tests/MonoGame.Extended.Entities.Tests/ComponentMapperTests.cs
new file mode 100644
index 00000000..ea8007c7
--- /dev/null
+++ b/Source/Tests/MonoGame.Extended.Entities.Tests/ComponentMapperTests.cs
@@ -0,0 +1,70 @@
+using Xunit;
+
+namespace MonoGame.Extended.Entities.Tests
+{
+ public class ComponentManagerTests
+ {
+ [Fact]
+ public void CreateComponentManager()
+ {
+ var manager = new ComponentManager();
+
+ }
+ }
+
+ public class ComponentMapperTests
+ {
+ [Fact]
+ public void CreateComponentMapper()
+ {
+ var mapper = new ComponentMapper