diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..f5a0c8e
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,3 @@
+generate-assets-class:
+ test -f MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Content/MonoGameBlank2dStartKit.mgcb || exit 1
+ node ./generate-asset-class.js MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Content/MonoGameBlank2dStartKit.mgcb > MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Content/Assets.cs
\ No newline at end of file
diff --git a/MonoGameBlank2dStartKit.sln.DotSettings.user b/MonoGameBlank2dStartKit.sln.DotSettings.user
index 7448f25..8082b2f 100644
--- a/MonoGameBlank2dStartKit.sln.DotSettings.user
+++ b/MonoGameBlank2dStartKit.sln.DotSettings.user
@@ -3,4 +3,5 @@
ForceIncluded
ForceIncluded
ForceIncluded
- ForceIncluded
\ No newline at end of file
+ ForceIncluded
+ ForceIncluded
\ No newline at end of file
diff --git a/MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Components.cs b/MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Components.cs
index a2db485..6053278 100644
--- a/MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Components.cs
+++ b/MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Components.cs
@@ -1,9 +1,34 @@
+using System;
using System.Numerics;
+using Microsoft.Xna.Framework.Graphics;
using MonoGameBlank2dStartKit.Core.Content;
namespace MonoGameBlank2dStartKit.Core;
-public readonly record struct Position(Vector2 Vector2);
-public readonly record struct Velocity(Vector2 Vector2);
+public readonly record struct Position(Vector2 Vector2)
+{
+ public Position(float x, float y) : this(new Vector2(x, y)) { }
+}
+
+public readonly record struct Velocity(Vector2 Vector2)
+{
+ public Velocity(float x, float y) : this(new Vector2(x, y)) { }
+}
+
+public readonly record struct Mass(int Value);
+
+public readonly record struct RotationSpeed(float Speed, float Amount = float.MaxValue, float Drag = 0)
+{
+}
+
+public readonly record struct Rotation(float Value, Vector2 Origin)
+{
+ public Rotation(float value, Texture2D texture) : this(value, CenterOfTexture(texture)) { }
+
+ private static Vector2 CenterOfTexture(Texture2D texture)
+ {
+ return new Vector2((float) texture.Width / 2, (float) texture.Height / 2);
+ }
+}
public readonly record struct Image(ImageId ImageId);
\ No newline at end of file
diff --git a/MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Content/Assets.cs b/MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Content/Assets.cs
index 48de28f..7bd9d56 100644
--- a/MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Content/Assets.cs
+++ b/MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Content/Assets.cs
@@ -1,3 +1,4 @@
+
using System;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
@@ -13,8 +14,7 @@ public class Assets
var allImageIds = Enum.GetValues();
_images =
[
- // TODO: Auto-generate this initialization
- content.Load("Images/ball")
+ content.Load("Images/ball"),
];
}
@@ -27,4 +27,4 @@ public class Assets
public enum ImageId
{
Ball
-}
\ No newline at end of file
+}
diff --git a/MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Content/Images/ball.png b/MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Content/Images/ball.png
index f23ff61..00c9328 100644
Binary files a/MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Content/Images/ball.png and b/MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Content/Images/ball.png differ
diff --git a/MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/MonoGameBlank2dStartKitGame.cs b/MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/MonoGameBlank2dStartKitGame.cs
index 701c1ed..575baa5 100644
--- a/MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/MonoGameBlank2dStartKitGame.cs
+++ b/MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/MonoGameBlank2dStartKitGame.cs
@@ -19,6 +19,8 @@ namespace MonoGameBlank2dStartKit.Core
public class MonoGameBlank2dStartKitGame : Game
{
private TextureDrawSystem TextureDrawSystem { get; set; }
+ private VelocitySystem VelocitySystem { get; set; }
+ private RotationSystem RotationSystem { get; set; }
// Resources for drawing.
private readonly GraphicsDeviceManager graphicsDeviceManager;
@@ -90,7 +92,9 @@ namespace MonoGameBlank2dStartKit.Core
_assets = new Assets(Content);
TextureDrawSystem = new TextureDrawSystem(World, _assets, _spriteBatch);
- Scenarios.Basic(World);
+ VelocitySystem = new VelocitySystem(World);
+ RotationSystem = new RotationSystem(World);
+ Scenarios.Basic(World, _assets);
base.LoadContent();
}
@@ -107,7 +111,9 @@ namespace MonoGameBlank2dStartKit.Core
|| Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
- // TODO: Add your update logic here
+ var elapsedGameTime = gameTime.ElapsedGameTime;
+ VelocitySystem.Update(elapsedGameTime);
+ RotationSystem.Update(elapsedGameTime);
base.Update(gameTime);
}
diff --git a/MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Scenarios.cs b/MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Scenarios.cs
index cd2e6b6..58ce55a 100644
--- a/MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Scenarios.cs
+++ b/MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Scenarios.cs
@@ -6,10 +6,13 @@ namespace MonoGameBlank2dStartKit.Core;
public static class Scenarios
{
- public static void Basic(World world)
+ public static void Basic(World world, Assets assets)
{
var ball = world.CreateEntity();
world.Set(ball, new Position(new Vector2(10, 10)));
world.Set(ball, new Image(ImageId.Ball));
+ world.Set(ball, new Velocity(40f, 40f));
+ world.Set(ball, new Rotation(0, assets.GetTexture2D(ImageId.Ball)));
+ world.Set(ball, new RotationSpeed(3f, Drag: 0.03f));
}
}
\ No newline at end of file
diff --git a/MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Systems/RotationSystem.cs b/MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Systems/RotationSystem.cs
new file mode 100644
index 0000000..43fc585
--- /dev/null
+++ b/MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Systems/RotationSystem.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Numerics;
+using MonoGameBlank2dStartKit.Core.Utils;
+using MoonTools.ECS;
+
+namespace MonoGameBlank2dStartKit.Core.Systems;
+
+public class RotationSystem : MoonTools.ECS.System
+{
+ private readonly Filter _filter;
+
+ public RotationSystem(World world) : base(world)
+ {
+ // Doesn't filter on Rotation, because it *should* blow up if RSpeed exists without Rotation.
+ _filter = FilterBuilder.Include().Build();
+ }
+
+ public override void Update(TimeSpan delta)
+ {
+ foreach (var entity in _filter.Entities)
+ {
+ var currentRotation = World.Get(entity);
+ var rotationSpeed = World.Get(entity);
+ float change = rotationSpeed.Speed * delta.SecFloat();
+ World.Set(entity, currentRotation with { Value = currentRotation.Value + change });
+
+ var newSpeed = rotationSpeed.Speed - (rotationSpeed.Drag * delta.SecFloat());
+ if (Math.Sign(newSpeed) != Math.Sign(rotationSpeed.Speed))
+ {
+ World.Remove(entity);
+ }
+ else
+ {
+ World.Set(entity, rotationSpeed with
+ {
+ Speed = newSpeed,
+ Amount = rotationSpeed.Amount - change,
+ });
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Systems/TextureDrawSystem.cs b/MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Systems/TextureDrawSystem.cs
index f15c250..a5ec2d7 100644
--- a/MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Systems/TextureDrawSystem.cs
+++ b/MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Systems/TextureDrawSystem.cs
@@ -9,23 +9,33 @@ namespace MonoGameBlank2dStartKit.Core.Systems;
public class TextureDrawSystem : MoonTools.ECS.System
{
private readonly Assets _assets;
- private readonly Filter _filter;
private readonly SpriteBatch _spriteBatch;
+ private readonly Filter _unrotatedFilter;
+ private readonly Filter _rotatedFilter;
+
public TextureDrawSystem(World world, Assets assets, SpriteBatch spriteBatch) : base(world)
{
_assets = assets;
_spriteBatch = spriteBatch;
- _filter = FilterBuilder.Include().Include().Build();
+ _unrotatedFilter = FilterBuilder.Include().Include().Exclude().Build();
+ _rotatedFilter = FilterBuilder.Include().Include().Include().Build();
}
public override void Update(TimeSpan delta)
{
- foreach (var entity in _filter.Entities)
+ foreach (var entity in _unrotatedFilter.Entities)
{
var texture = _assets.GetTexture2D(World.Get(entity).ImageId);
var position = World.Get(entity).Vector2;
_spriteBatch.Draw(texture, position, Color.White);
}
+ foreach (var entity in _rotatedFilter.Entities)
+ {
+ var texture = _assets.GetTexture2D(World.Get(entity).ImageId);
+ var position = World.Get(entity).Vector2;
+ var rotation = World.Get(entity);
+ _spriteBatch.Draw(texture, position, null, Color.White, rotation.Value, rotation.Origin, new Vector2(1, 1), SpriteEffects.None, 1);
+ }
}
}
\ No newline at end of file
diff --git a/MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Systems/VelocitySystem.cs b/MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Systems/VelocitySystem.cs
new file mode 100644
index 0000000..6c7c26e
--- /dev/null
+++ b/MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Systems/VelocitySystem.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Numerics;
+using MonoGameBlank2dStartKit.Core.Utils;
+using MoonTools.ECS;
+
+namespace MonoGameBlank2dStartKit.Core.Systems;
+
+public class VelocitySystem : MoonTools.ECS.System
+{
+ private readonly Filter _filter;
+
+ public VelocitySystem(World world) : base(world)
+ {
+ _filter = FilterBuilder.Include().Include().Build();
+ }
+
+ public override void Update(TimeSpan delta)
+ {
+ float deltaSec = delta.SecFloat();
+ foreach (var entity in _filter.Entities)
+ {
+ var currentPosition = World.Get(entity).Vector2;
+ var velocity = World.Get(entity).Vector2;
+ World.Set(entity, new Position(
+ currentPosition.X + (velocity.X * deltaSec),
+ currentPosition.Y + (velocity.Y * deltaSec)
+ ));
+ }
+ }
+}
\ No newline at end of file
diff --git a/MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Utils/TimeSpanExtensions.cs b/MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Utils/TimeSpanExtensions.cs
new file mode 100644
index 0000000..72a675a
--- /dev/null
+++ b/MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Utils/TimeSpanExtensions.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace MonoGameBlank2dStartKit.Core.Utils;
+
+public static class TimeSpanExtensions
+{
+ public static float SecFloat(this TimeSpan span)
+ {
+ return (float)span.Ticks / TimeSpan.TicksPerSecond;
+ }
+}
\ No newline at end of file
diff --git a/generate-asset-class.js b/generate-asset-class.js
new file mode 100644
index 0000000..02b1676
--- /dev/null
+++ b/generate-asset-class.js
@@ -0,0 +1,65 @@
+const fs = require('fs')
+
+const mgcbFile = process.argv[2]
+if (!mgcbFile) {
+ return 1
+}
+
+const fileContents = fs.readFileSync(mgcbFile, 'utf8')
+/** @type string[] */
+const lines = fileContents.split('\n')
+
+/** @type {Object.} */
+const types = {}
+
+lines.forEach(line => {
+ const prefix = '#begin '
+ if (!line.startsWith(prefix)) {
+ return
+ }
+ line = line.substring(prefix.length)
+ const [type, name] = line.split('/')
+ types[type] ??= []
+ types[type].push(name)
+})
+
+let imageIdTextureLoads = ''
+let imageIdEnumString = ''
+
+types['Images'].forEach(image => {
+ const [name, ext] = image.split('.')
+ imageIdTextureLoads += '\n '
+ imageIdTextureLoads += `content.Load("Images/${name}"),`
+
+ imageIdEnumString += '\n '
+ imageIdEnumString += name[0].toUpperCase() + name.substring(1)
+})
+
+console.log(`
+using System;
+using Microsoft.Xna.Framework.Content;
+using Microsoft.Xna.Framework.Graphics;
+
+namespace MonoGameBlank2dStartKit.Core.Content;
+
+public class Assets
+{
+ private readonly Texture2D[] _images;
+
+ public Assets(ContentManager content)
+ {
+ var allImageIds = Enum.GetValues();
+ _images =
+ [${imageIdTextureLoads}
+ ];
+ }
+
+ public Texture2D GetTexture2D(ImageId imageId)
+ {
+ return _images[(int)imageId];
+ }
+}
+
+public enum ImageId
+{${imageIdEnumString}
+}`)
\ No newline at end of file