Skip to content

Commit

Permalink
Merge pull request #846 from tigurx/tiled_animation_flip_fix
Browse files Browse the repository at this point in the history
Fixes incorrect rendering of flipped animation tiles
  • Loading branch information
AristurtleDev authored May 18, 2024
2 parents 455ea4d + 55bfe25 commit 9c5f7cd
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
using Microsoft.Xna.Framework.Graphics;
using System;

namespace MonoGame.Extended.Tiled.Renderers
{
public sealed class TiledMapAnimatedLayerModel : TiledMapLayerModel
{
public TiledMapAnimatedLayerModel(GraphicsDevice graphicsDevice, Texture2D texture, VertexPositionTexture[] vertices, ushort[] indices, TiledMapTilesetAnimatedTile[] animatedTilesetTiles)
public TiledMapAnimatedLayerModel(GraphicsDevice graphicsDevice, Texture2D texture, VertexPositionTexture[] vertices, ushort[] indices, TiledMapTilesetAnimatedTile[] animatedTilesetTiles, TiledMapTileFlipFlags[] animatedTilesetTileFlipFlags)
: base(graphicsDevice, texture, vertices, indices)
{
Vertices = vertices;
AnimatedTilesetTiles = animatedTilesetTiles;
_animatedTilesetFlipFlags = animatedTilesetTileFlipFlags;
}

public VertexPositionTexture[] Vertices { get; }
public TiledMapTilesetAnimatedTile[] AnimatedTilesetTiles { get; }
private readonly TiledMapTileFlipFlags[] _animatedTilesetFlipFlags;

public ReadOnlySpan<TiledMapTileFlipFlags> AnimatedTilesetFlipFlags => _animatedTilesetFlipFlags;

protected override VertexBuffer CreateVertexBuffer(GraphicsDevice graphicsDevice, int vertexCount)
{
Expand All @@ -24,4 +29,4 @@ protected override IndexBuffer CreateIndexBuffer(GraphicsDevice graphicsDevice,
return new DynamicIndexBuffer(graphicsDevice, IndexElementSize.SixteenBits, indexCount, BufferUsage.WriteOnly); ;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,21 @@ public class TiledMapAnimatedLayerModelBuilder : TiledMapLayerModelBuilder<Tiled
public TiledMapAnimatedLayerModelBuilder()
{
AnimatedTilesetTiles = new List<TiledMapTilesetAnimatedTile>();
AnimatedTilesetFlipFlags = new List<TiledMapTileFlipFlags>();
}

public List<TiledMapTilesetAnimatedTile> AnimatedTilesetTiles { get; }
public List<TiledMapTileFlipFlags> AnimatedTilesetFlipFlags { get; }

protected override void ClearBuffers()
{
AnimatedTilesetTiles.Clear();
AnimatedTilesetFlipFlags.Clear();
}

protected override TiledMapAnimatedLayerModel CreateModel(GraphicsDevice graphicsDevice, Texture2D texture)
{
return new TiledMapAnimatedLayerModel(graphicsDevice, texture, Vertices.ToArray(), Indices.ToArray(), AnimatedTilesetTiles.ToArray());
return new TiledMapAnimatedLayerModel(graphicsDevice, texture, Vertices.ToArray(), Indices.ToArray(), AnimatedTilesetTiles.ToArray(), AnimatedTilesetFlipFlags.ToArray());
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ private IEnumerable<TiledMapLayerModel> CreateTileLayerModels(TiledMap map, Tile
if (tilesetTile is TiledMapTilesetAnimatedTile animatedTilesetTile)
{
animatedLayerBuilder.AddSprite(texture, position, sourceRectangle, flipFlags);
animatedTilesetTile.CreateTextureRotations(tileset, flipFlags);
animatedLayerBuilder.AnimatedTilesetTiles.Add(animatedTilesetTile);
animatedLayerBuilder.AnimatedTilesetFlipFlags.Add(flipFlags);

if (animatedLayerBuilder.IsFull)
layerModels.Add(animatedLayerBuilder.Build(_graphicsDevice, texture));
Expand Down
7 changes: 3 additions & 4 deletions src/cs/MonoGame.Extended.Tiled/Renderers/TiledMapRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,9 @@ private static unsafe void UpdateAnimatedLayerModels(IEnumerable<TiledMapAnimate
fixed (VertexPositionTexture* fixedVerticesPointer = animatedModel.Vertices)
{
var verticesPointer = fixedVerticesPointer;

foreach (var animatedTile in animatedModel.AnimatedTilesetTiles)
{
var currentFrameTextureCoordinates = animatedTile.CurrentAnimationFrame.TextureCoordinates;
for (int i = 0; i < animatedModel.AnimatedTilesetTiles.Length; i++)
{
var currentFrameTextureCoordinates = animatedModel.AnimatedTilesetTiles[i].CurrentAnimationFrame.GetTextureCoordinates(animatedModel.AnimatedTilesetFlipFlags[i]);

// ReSharper disable ArrangeRedundantParentheses
(*verticesPointer++).TextureCoordinate = currentFrameTextureCoordinates[0];
Expand Down
8 changes: 8 additions & 0 deletions src/cs/MonoGame.Extended.Tiled/TiledMapTilesetAnimatedTile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ public TiledMapTilesetAnimatedTile(int localTileIdentifier,
CurrentAnimationFrame = AnimationFrames[0];
}

public void CreateTextureRotations(TiledMapTileset tileset, TiledMapTileFlipFlags flipFlags)
{
for (int i = 0; i < AnimationFrames.Count; i++)
{
AnimationFrames[i].CreateTextureRotations(tileset, flipFlags);
}
}

public void Update(GameTime gameTime)
{
_timer += gameTime.ElapsedGameTime;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;

namespace MonoGame.Extended.Tiled
Expand All @@ -8,6 +9,7 @@ public struct TiledMapTilesetTileAnimationFrame
public readonly int LocalTileIdentifier;
public readonly TimeSpan Duration;
public readonly Vector2[] TextureCoordinates;
private readonly Dictionary<TiledMapTileFlipFlags, Vector2[]> _flipDictionary = new Dictionary<TiledMapTileFlipFlags, Vector2[]>();

internal TiledMapTilesetTileAnimationFrame(TiledMapTileset tileset, int localTileIdentifier, int durationInMilliseconds)
{
Expand All @@ -17,6 +19,101 @@ internal TiledMapTilesetTileAnimationFrame(TiledMapTileset tileset, int localTil
CreateTextureCoordinates(tileset);
}

public Vector2[] GetTextureCoordinates(TiledMapTileFlipFlags flipFlags)
{
if (!_flipDictionary.TryGetValue(flipFlags, out Vector2[] flippedTextureCoordiantes))
{
return TextureCoordinates;
}
else
{
return flippedTextureCoordiantes;
}
}

public void CreateTextureRotations(TiledMapTileset tileset, TiledMapTileFlipFlags flipFlags)
{
if (!_flipDictionary.ContainsKey(flipFlags))
{
if (flipFlags == TiledMapTileFlipFlags.None)
{
_flipDictionary.Add(flipFlags, TextureCoordinates);
}
else
{
_flipDictionary.Add(flipFlags, TransformTextureCoordinates(tileset, flipFlags));
}
}
}

public Vector2[] TransformTextureCoordinates(TiledMapTileset tileset, TiledMapTileFlipFlags flipFlags)
{
var sourceRectangle = tileset.GetTileRegion(LocalTileIdentifier);
var texture = tileset.Texture;
var texelLeft = (float)sourceRectangle.X / texture.Width;
var texelTop = (float)sourceRectangle.Y / texture.Height;
var texelRight = (sourceRectangle.X + sourceRectangle.Width) / (float)texture.Width;
var texelBottom = (sourceRectangle.Y + sourceRectangle.Height) / (float)texture.Height;

var flipDiagonally = (flipFlags & TiledMapTileFlipFlags.FlipDiagonally) != 0;
var flipHorizontally = (flipFlags & TiledMapTileFlipFlags.FlipHorizontally) != 0;
var flipVertically = (flipFlags & TiledMapTileFlipFlags.FlipVertically) != 0;
var transform = new Vector2[4];

transform[0].X = texelLeft;
transform[0].Y = texelTop;

transform[1].X = texelRight;
transform[1].Y = texelTop;

transform[2].X = texelLeft;
transform[2].Y = texelBottom;

transform[3].X = texelRight;
transform[3].Y = texelBottom;

if (flipDiagonally)
{
FloatHelper.Swap(ref transform[1].X, ref transform[2].X);
FloatHelper.Swap(ref transform[1].Y, ref transform[2].Y);
}

if (flipHorizontally)
{
if (flipDiagonally)
{
FloatHelper.Swap(ref transform[0].Y, ref transform[1].Y);
FloatHelper.Swap(ref transform[2].Y, ref transform[3].Y);
}
else
{
FloatHelper.Swap(ref transform[0].X, ref transform[1].X);
FloatHelper.Swap(ref transform[2].X, ref transform[3].X);
}
}

if (flipVertically)
{
if (flipDiagonally)
{
FloatHelper.Swap(ref transform[0].X, ref transform[2].X);
FloatHelper.Swap(ref transform[1].X, ref transform[3].X);
}
else
{
FloatHelper.Swap(ref transform[0].Y, ref transform[2].Y);
FloatHelper.Swap(ref transform[1].Y, ref transform[3].Y);
}
}

transform[0] = transform[0];
transform[1] = transform[1];
transform[2] = transform[2];
transform[3] = transform[3];

return transform;
}

private void CreateTextureCoordinates(TiledMapTileset tileset)
{
var sourceRectangle = tileset.GetTileRegion(LocalTileIdentifier);
Expand Down Expand Up @@ -44,4 +141,4 @@ public override string ToString()
return $"{LocalTileIdentifier}:{Duration}";
}
}
}
}

0 comments on commit 9c5f7cd

Please sign in to comment.