TheBoneJarmer / TiledCS

TiledCS is a dotnet library for loading Tiled tilesets and maps
MIT License
139 stars 51 forks source link

how to loop through Tiles in a layer? #59

Closed ghost closed 2 years ago

ghost commented 2 years ago

Hi

In the past I used TiledSharp and looped through a tiled map to draw it like this (below is TiledSharp code). I changed the code to TiledCS and try to get all layers of a map using:

map.Layers[i]

then I can't get the list of Tiles by doing map.Layers[i].Tiles

There doesn't exist a way to get all Tiles from a layer. How to loop through all tiles then in a for-loop?

How to do this please? Please give small code example for the 2nd for-loop to loop through all tiles of a layer.

`public void Draw(Matrix matrix) {

        spriteBatch.Begin(
            SpriteSortMode.Deferred,
            samplerState:SamplerState.PointClamp,
            effect:null,
            blendState:null,
            rasterizerState:null,
            depthStencilState:null,
            transformMatrix:matrix);
        for (var j = 0; j < map.TileLayers.Count; j++)
        {
            for (var i = 0; i < map.TileLayers[j].Tiles.Count; i++)
            {
                int gid = map.TileLayers[j].Tiles[i].Gid;
                if (gid == 0)
                {
                    //If empty tile then do nothing
                }
                else
                {
                    int tileFrame = gid - 1;
                    int column = tileFrame % tilesetTilesWide;
                    int row = (int)Math.Floor((double)tileFrame / (double)tilesetTilesWide);
                    float x = (i % map.Width) * map.TileWidth;
                    float y = (float)Math.Floor(i / (double)map.Width) * map.TileHeight;

                    Rectangle tilesetRec = new Rectangle((tileWidth) * column, (tileHeight) * row, tileWidth, tileHeight);
                    spriteBatch.Draw(tileset, new Rectangle((int)x, (int)y, tileWidth, tileHeight), tilesetRec, Color.White);
                }
            }

        }
        spriteBatch.End();
    }`
TheBoneJarmer commented 2 years ago

Hey

Within a layer whose type equals that of tilelayer, exists a field of type int[] called data. This array represents the gids of all tiles. A gid is a tile index from a tileset, not the tile id as some think. In order to render a specific tile from a tileset into your spritebatch, you would need to link the gid to a tileset.

Tiled stores its tiles as a gid value, which is an index from a tileset. If you have multiple tilesets, you need to figure out which gid belongs to which. To help you with this process, I have added some helper methods to make this more easier for you. Let's say for example you have the following list of tilesets:

main.tsx
dungeon.tsx
overworld.tsx

And each tileset has 10 tiles horizontal and 10 tiles vertical, then the gid's per tileset would look like this:

main.tsx 1..100
dungeon.tsx 101..200
overworld.tsx 201..300

Why? Because a tileset of 10x10 has 100 tiles in total and since 0 is used to tell that there is no tile set, it starts with 1. Then the next included tileset's gid starts with the total amount of tiles from the tileset included before. Therefore you should be careful when extending an existing tileset when your map has already been drawn. The helper method TiledMap.GetTiledMapTileset returns a dictionary where the key represent the tileset's first gid and the value represents the tileset which is of type TiledTileset.

Warning! This works with external tilesets only for the moment. Support for embedded is on the way

Once you have the tileset and the gid, you can use that data to retrieve the tile's source rect. This would be similar to your Rectangle tilesetRec. You can than use this data to render the tile. See the example below. You may need to tweak things a bit to fit for you case but below should do the trick. Be aware the layer.width does not equal the layer's total width in pixels. The layer.width and layer.height value represents the layer's horizontal tiles and vertical tiles. So you need to know your tile's size in pixels too, which can be fetched from the TiledMap.TileWidth and TiledMap.TileHeight property.

foreach (var layer in map.Layers)
{
    for (var x = 0; x < layer.width; x++)
    {
        for (var y = 0; y < layer.height; y++)
        {
            var gid = layer.data[(y * layer.height) + x];

            if (gid == 0)
            {
                continue;
            }

            var mapTileset = tiledMap.GetTiledMapTileset(gid);
            var tiledTileset = tiledTilesets[mapTileset.firstgid];
            var srcRect = tiledMap.GetSourceRect(mapTileset, tiledTileset, gid);

            // Render method goes here
        }
    }
}

With kind regards, TheBoneJarmer

ghost commented 2 years ago

I don't understand ANTYHING of your library and therefore keep using TiledSharp. Your library makes everything more complicated then needed.

ghost commented 2 years ago

STUPID CRAP TILEDCS

TheBoneJarmer commented 2 years ago

Okay enough. I gave exactly what you asked and it is still not enough. Just fuck off and leave me in peace. All you do is bitch about TiledCS when you try nothing at all. I am tired of dealing with this crap and I would like to let you know I reported you and I am going to block you.

TheBoneJarmer commented 2 years ago

And don't play stupid. I know it is you Jess. First you spam my Discord, my email and my GitHub by opening up over 18!! issues. Enough is enough.