diff --git a/Demos/AnimationDemo.cs b/Demos/AnimationDemo.cs index abfccf8..d394575 100644 --- a/Demos/AnimationDemo.cs +++ b/Demos/AnimationDemo.cs @@ -19,13 +19,20 @@ namespace Demos { public override void LoadContent() { base.LoadContent(); - var tex = LoadContent("Textures/Anim"); + // create a uniform texture atlas with a width and height of 4 + // this means that, no matter how many pixels the texture has, it will always have 4 * 4 regions in total + // this allows for texture artists to change the resolution of a texture atlas without every texture region + // using it having wrong coordinates and/or sizes + // the regions that are part of the atlas are then referenced by region coordinates rather than texture coordinates + // (as seen below) + var atlas = new UniformTextureAtlas(LoadContent("Textures/Anim"), 4, 4); - // create the four animations by supplying the time per frame, the texture and the four regions used - var downAnim = new SpriteAnimation(0.2F, tex, new Rectangle(0, 0, 8, 8), new Rectangle(0, 8, 8, 8), new Rectangle(0, 16, 8, 8), new Rectangle(0, 24, 8, 8)) {Name = "Down"}; - var upAnim = new SpriteAnimation(0.2F, tex, new Rectangle(8, 0, 8, 8), new Rectangle(8, 8, 8, 8), new Rectangle(8, 16, 8, 8), new Rectangle(8, 24, 8, 8)) {Name = "Up"}; - var leftAnim = new SpriteAnimation(0.2F, tex, new Rectangle(16, 0, 8, 8), new Rectangle(16, 8, 8, 8), new Rectangle(16, 16, 8, 8), new Rectangle(16, 24, 8, 8)) {Name = "Left"}; - var rightAnim = new SpriteAnimation(0.2F, tex, new Rectangle(24, 0, 8, 8), new Rectangle(24, 8, 8, 8), new Rectangle(24, 16, 8, 8), new Rectangle(24, 24, 8, 8)) {Name = "Right"}; + // create the four animations by supplying the time per frame, and the four regions used + // note that you don't need to use a texture atlas for this, you can also simply supply the texture and the regions manually here + var downAnim = new SpriteAnimation(0.2F, atlas[0, 0], atlas[0, 1], atlas[0, 2], atlas[0, 3]) {Name = "Down"}; + var upAnim = new SpriteAnimation(0.2F, atlas[1, 0], atlas[1, 1], atlas[1, 2], atlas[1, 3]) {Name = "Up"}; + var leftAnim = new SpriteAnimation(0.2F, atlas[2, 0], atlas[2, 1], atlas[2, 2], atlas[2, 3]) {Name = "Left"}; + var rightAnim = new SpriteAnimation(0.2F, atlas[3, 0], atlas[3, 1], atlas[3, 2], atlas[3, 3]) {Name = "Right"}; // create a sprite animation group which manages a list of animations and figures out which one should // be playing right now based on supplied conditions @@ -41,7 +48,7 @@ namespace Demos { // you can also add a priority to an animation in the group (10 in this case, which is higher than the default of 0) // if two animations' playing conditions are both true, then the one with the higher priority will be picked to play // in this instance, a standing "animation" is displayed when we're facing down and also holding the space key - this.group.Add(new SpriteAnimation(1F, tex, new Rectangle(0, 0, 8, 8)) {Name = "DownStanding"}, () => this.facing == Direction2.Down && this.InputHandler.IsKeyDown(Keys.Space), 10); + this.group.Add(new SpriteAnimation(1F, atlas[0, 0]) {Name = "DownStanding"}, () => this.facing == Direction2.Down && this.InputHandler.IsKeyDown(Keys.Space), 10); // you can also add a callback to see when the animation used changes this.group.OnAnimationChanged += (anim, newAnim) => { @@ -67,7 +74,7 @@ namespace Demos { } public override void DoDraw(GameTime gameTime) { - this.GraphicsDevice.Clear(Color.Black); + this.GraphicsDevice.Clear(Color.CornflowerBlue); this.SpriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp, transformMatrix: Matrix.CreateScale(10)); // draw the group's current region diff --git a/Demos/Content/Textures/Anim.png b/Demos/Content/Textures/Anim.png index adba882..d4ddb1e 100644 Binary files a/Demos/Content/Textures/Anim.png and b/Demos/Content/Textures/Anim.png differ diff --git a/Demos/GameImpl.cs b/Demos/GameImpl.cs index 38c5b40..a54cacd 100644 --- a/Demos/GameImpl.cs +++ b/Demos/GameImpl.cs @@ -17,8 +17,8 @@ namespace Demos { static GameImpl() { Demos.Add("Ui", game => new UiDemo(game)); - Demos.Add("Animation", game => new AnimationDemo(game)); - Demos.Add("AutoTiling", game => new AutoTilingDemo(game)); + Demos.Add("Animation and Texture Atlas", game => new AnimationDemo(game)); + Demos.Add("Auto Tiling", game => new AutoTilingDemo(game)); Demos.Add("Pathfinding", game => new PathfindingDemo(game)); } diff --git a/MLEM/Textures/UniformTextureAtlas.cs b/MLEM/Textures/UniformTextureAtlas.cs new file mode 100644 index 0000000..9197314 --- /dev/null +++ b/MLEM/Textures/UniformTextureAtlas.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace MLEM.Textures { + public class UniformTextureAtlas { + + public readonly Texture2D Texture; + public readonly int RegionAmountX; + public readonly int RegionAmountY; + public TextureRegion this[Point point] => this.regions.TryGetValue(point, out var region) ? region : null; + public TextureRegion this[int x, int y] => this[new Point(x, y)]; + + private readonly Dictionary regions = new Dictionary(); + + public UniformTextureAtlas(Texture2D texture, int regionAmountX, int regionAmountY) { + this.Texture = texture; + this.RegionAmountX = regionAmountX; + this.RegionAmountY = regionAmountY; + + var regionWidth = texture.Width / regionAmountX; + var regionHeight = texture.Height / regionAmountY; + for (var x = 0; x < regionAmountX; x++) { + for (var y = 0; y < regionAmountY; y++) { + this.regions.Add(new Point(x, y), new TextureRegion(texture, x * regionWidth, y * regionHeight, regionWidth, regionHeight)); + } + } + } + + } +} \ No newline at end of file