From 1ff7806c7ab26099f6b5fdb5fbfefaac239b0348 Mon Sep 17 00:00:00 2001 From: Sage Vaillancourt Date: Thu, 24 Apr 2025 12:57:35 -0400 Subject: [PATCH] Add some more simple systems. Generate Assets.cs with generate-asset-class.js Currently only processes Images/ in the .mgcb --- Makefile | 3 + MonoGameBlank2dStartKit.sln.DotSettings.user | 3 +- .../Components.cs | 29 +++++++- .../Content/Assets.cs | 6 +- .../Content/Images/ball.png | Bin 8368 -> 2850 bytes .../MonoGameBlank2dStartKitGame.cs | 10 ++- .../MonoGameBlank2dStartKit.Core/Scenarios.cs | 5 +- .../Systems/RotationSystem.cs | 42 +++++++++++ .../Systems/TextureDrawSystem.cs | 16 ++++- .../Systems/VelocitySystem.cs | 30 ++++++++ .../Utils/TimeSpanExtensions.cs | 11 +++ generate-asset-class.js | 65 ++++++++++++++++++ 12 files changed, 208 insertions(+), 12 deletions(-) create mode 100644 Makefile create mode 100644 MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Systems/RotationSystem.cs create mode 100644 MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Systems/VelocitySystem.cs create mode 100644 MonoGameBlank2dStartKit/MonoGameBlank2dStartKit.Core/Utils/TimeSpanExtensions.cs create mode 100644 generate-asset-class.js 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 f23ff6104f864b4a24c2476c709db1cf0cfab114..00c9328d31156185d72b5e6a74ba7d7938c05f1d 100644 GIT binary patch delta 2798 zcmV004R> z004l5008;`004mK004C`008P>0026e000+ooVrmwks&aD=>!-MC>|!p3F80&3T8<} zK~#9!)mwQ?Q`s8-l|`S59akhSR1NBT4hcAb0xl6U8F7nCqW+U^0MU0AULkF8pfRv}q8F#TYYY4Ag3MlSm}eZ{508 z1)u>y4S;F@1|bJ05~$yK0G1y)a%4exc=*_f6DNX*aPQtd%$zwBqeqX%fB^%Xerzxp zpwVd1(9i(6T>da8C+9kVO91Ne1!Dw&-G>h!exp!-D2QPgvV&z=%FoXyZ=uua=+>=U zw07;<`vBGe2>j9*&%Su^qFJZY^~peac{#PUwGkh9^ym@o-Md!{AO(Q`=VZJefQ;PS zT(e%UcRFB(VMr#E5#Ok)sv-b&0KWSi%txlAr2PK;`E$1emCNP5wgaC~C=|47*Dgv* zN;(67V9=*xJ~b~d&&;wcr$I`kQW6r?)zzd>C@3Q%qtRw*1jFCv&!7LFnwlE7gL?Pw z9VwMcI)3~(rKYA*b91wxLO6T&ENQh`x^Urw*`_3U$H2tI#0oBq{Px>#v}w~O0?@1N z-@l()TU&W&o?#e@jg2J$R8UYrH*ek~0PA>vWq$qo^%d?0uh;8o&z?OFjDOrNUAn}p zPAD!e?$v*Cax$Gif1UvRz>B6&NJwzYd}(PZNhA`t%-h?NB}?e>#8sL0g`%P&E_CL3%m0r`rP3vT z^U2A{UNdiRJ9q9RmSst&(~(A_q1xJ7QYaJ-?dj8}q|s>T?c29RL}WA?DJm+83k@>> zi8CexocumDH#hg^s3=FP($UcYolb|$%uJj)bH?XAmYJCe09deK0YXATFlyAOzXBDJ z2t?HVzu9cY%aCe^4_)?GiH!0Ptq0CYBh<)Vy?8dbDfmU0O;Jgb9DFaU3&HEl>=eEmjmmp1!7m7+Vketv!g;O`FH zr=_JeS*=!1gx0QI>+|gU;sCkA)vH%s(mrtD00H>f&bOcK@3$*gt_=0}=ayiZG-;Ag zwm&^RovRJ^7>gDy!qTNnojx~znM}yZ$@%BU0$3a#9?qG_*I$3_^#J4I;?S3a#TNnt z1CgGd?%c@{i7;cvjFAAo?H0g+0|%B295|3Ok;#)Mdp*D{TehHo|NeqzY+_}s?6B7kbSp^0LV)g2O)!4jwGXOxX zR>Nd6bvLnCjI^}0#H_3=1OSMiIB}w9hY2DPGBYy~8XAfx;z%VO%(sYpmjaCr9O#S1)n@&pkP5wZ5Ha+c9(^hndTwY5=cX{pB=`u+R&bmhtw z5*jL%iZmLH%P`uORgUt1n=@xl_~5~VJ(BR9J9jX5?p)80p+q7iCMKe)s!Grm@bu|Z zgoK2+)B!BZ0zib{!i5Wmd(yc|r9wnRgx6+l`0x+p^m@G@%y)HlVbGvKZk2dlT^#@f z`vDl|34zCtA44LM_%z7)_;}pDeH&J*m3IL=dh`g9k&!On@%Q(C$Cxo=0APZjL?Q|1 z+PPY-Modf$Kc}bj=Ap8(l6L{9)#~n5<}&OZG2(+G#4wCUvp;_PcwPoNWXKQ%1qI>d z%a^<{-`LoQ>C>lkde^>+{hmL6&gp~p_I3;%I+WMhijIzkQmI5&R~Ik+)zs8r+&FGK zS}YdZl7ayN#3cxS66%bPVHhedF6QN&(3RZ+30Ri(N*{D}b)mGh6tic~ z_UOCT)>Z&e2S}yTrdhLQMKKHmX8}=NU7b%6AXn2Um&+l47K{Jdp8zZt3yel%FL(Rh zyLZrPwdm;RfI^|b#*G^h5D?%IJ)81>0{{mN1_Kop74^AK{`lh$UiK&#G&D4Lm0)@J z@S(Q_7Eyixel-{jh>D7WNF;J-!-fq*Zf@=;DLlx}&-d!P>({S){LQmx&j6qn077Ll z8EG^cmr|~Oudf$$_Fun#?Nge~VzGEcFD)&t+MW<;uC1+gYX%An3k9A1va&LtzSn3p z9$Ag7tgP~$za2Fijc%nZ)GE;H^*(2rT^;0pj0X=MP_L92fa@xi3iIdBcPY7J$Byyl zwe^HdCgUXr;EG><`9%ky_mbPadv}v9Wi04f-p6=<`}QqOm@vWT6~HyoVq0wvX>n}d zzWv`^V*I3}Bwhm;nM~%<>^Vb2Lj$MxN=ixq;Jq@dIn0Jot>o7Xu6v#_mpK>I(F=s;O5U_u~14%iW1HX!kpqq zE(7rO9zbbnsaK4Lg@sW?MTOh`b8>QAmdUxpDOVL?M~@!m#TjaDZnjr;a%!omshrY( zU$$C-dA@9~ehCQ)6}NBSrd6v}ISiz(u8ud4kY!maDJh|T{rWj&JT^9#XJSwDrEGsMHy0cJSXlUfadEOQLF}G6bLN}NmoHOGON&>`S5{U!I5|RIofY)*^r}^>7A#w~Y-~(S z3_?Oe`aF5ESS-+LwPHVZ#Q5g@r+@)e3%jTJ#B4M)&pk#fukDo;7P$ zFvBomot>Ruoj7pnjUK0Qvy)9h*WY_2a2P~tGA30;8iU0rr07*qoM6N<$f{uMv AwEzGB delta 8362 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 As{jB1 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