craftworkgames / MonoGame.Extended

Extensions to make MonoGame more awesome
http://www.monogameextended.net/
Other
1.43k stars 324 forks source link

[TiledMapRenderer] Misalignment of tiles when using different tilesets of different cell sizes #697

Open SilenceOfTheLambdas opened 3 years ago

SilenceOfTheLambdas commented 3 years ago

If you add tiles to a map (32x32 grid) from a tileset that uses a 32x32 grid, the map will render perfectly. But, if you then add some tiles to your map from a tileset that's a different size (i.e. 64x128), those tiles will be misaligned.

When using tiles only from tilesets that match the map's tile size (32x32) Game: image Tiled Editor (How it should look): image

When using tiles from a tileset that matches the map tile size, and some tiles from a tileset that does not match the map's tile size Game: image

Tiled Editor (How it should look): image

lithiumtoast commented 3 years ago

Interesting. Could you post the project with the files used for testing this?

SilenceOfTheLambdas commented 3 years ago

Interesting. Could you post the project with the files used for testing this?

Here is a link to the repo: https://github.com/sudo-make/Capstone-Project. You should just be able to import the project using Rider.

lithiumtoast commented 3 years ago

Reproduced. The problem is the position of the vertices when building the GPU memory from the tiled map's data.

Uraxys commented 3 years ago

Is there any update on this issue? Currently running into it myself now.

lithiumtoast commented 3 years ago

I believe the issue was resolved in offline communications.

@Uraxys could you send me a project with this issue? I'll take a look.

Uraxys commented 3 years ago

I believe the issue was resolved in offline communications.

@Uraxys could you send me a project with this issue? I'll take a look.

Here you go https://github.com/Uraxys/MonoGameDemo

Here is also a picture of how it should look compared to what it looks like in game. (In tiled) Picture1 (In game) Picture2

Uraxys commented 3 years ago

Update: I was able to fix the issue by adding this line inside the CreateTileLayerModels method in the TiledMapModelBuilder class. It makes larger tiles "go" upwards instead of downwards, as that was my issue.

if (tileset.TileHeight > tileLayer.TileHeight) tilePosition.Y -= tileset.TileHeight - tileLayer.TileHeight;

No idea if this is the best solution, but wanted to share it incase it helps fix the issue.

tigurx commented 5 months ago

Update: I was able to fix the issue by adding this line inside the CreateTileLayerModels method in the TiledMapModelBuilder class. It makes larger tiles "go" upwards instead of downwards, as that was my issue.

if (tileset.TileHeight > tileLayer.TileHeight) position.Y -= tileset.TileHeight - tileLayer.TileHeight;

No idea if this is the best solution, but wanted to share it incase it helps fix the issue.

This fixed it for me also. I wasn't sure if it was the right solution though so I never submitted a PR.

private IEnumerable<TiledMapLayerModel> CreateTileLayerModels(TiledMap map, TiledMapTileLayer tileLayer)
{
    var layerModels = new List<TiledMapLayerModel>();
    var staticLayerBuilder = new TiledMapStaticLayerModelBuilder();
    var animatedLayerBuilder = new TiledMapAnimatedLayerModelBuilder();

    foreach (var tileset in map.Tilesets)
    {
        var firstGlobalIdentifier = map.GetTilesetFirstGlobalIdentifier(tileset);
        var lastGlobalIdentifier = tileset.TileCount + firstGlobalIdentifier - 1;
        var texture = tileset.Texture;

        foreach (var tile in tileLayer.Tiles.Where(t => firstGlobalIdentifier <= t.GlobalIdentifier && t.GlobalIdentifier <= lastGlobalIdentifier))
        {
            var tileGid = tile.GlobalIdentifier;
            var localTileIdentifier = tileGid - firstGlobalIdentifier;
            var position = GetTilePosition(map, tile);
            var sourceRectangle = tileset.GetTileRegion(localTileIdentifier);
            var flipFlags = tile.Flags;

            if (tileset.TileHeight > tileLayer.TileHeight) position.Y -= tileset.TileHeight - tileLayer.TileHeight;

            // animated tiles
            var tilesetTile = tileset.Tiles.FirstOrDefault(x => x.LocalTileIdentifier == localTileIdentifier);
            if (tilesetTile?.Texture is not null)
            {
                position.Y += map.TileHeight - sourceRectangle.Height;
                texture = tilesetTile.Texture;
            }

            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));
            }
            else
            {
                staticLayerBuilder.AddSprite(texture, position, sourceRectangle, flipFlags);

                if (staticLayerBuilder.IsFull)
                    layerModels.Add(staticLayerBuilder.Build(_graphicsDevice, texture));
            }
        }

        if (staticLayerBuilder.IsBuildable)
            layerModels.Add(staticLayerBuilder.Build(_graphicsDevice, texture));

        if (animatedLayerBuilder.IsBuildable)
            layerModels.Add(animatedLayerBuilder.Build(_graphicsDevice, texture));
    }

    return layerModels;
}

This was the line I had added as suggested by Uraxys if (tileset.TileHeight > tileLayer.TileHeight) position.Y -= tileset.TileHeight - tileLayer.TileHeight;