Extended: Tileset Collision Data

How do I retrieve the collision data from the tilesets?

I dont necessarily need all the collision data, just the tileset tiles that are collidable.

EDIT: Also…Is it better to do collisions according to tilesets (i.e. specific tiles on the tileset are collidable) or using tilemap (i.e. specific tiles on the tilemap are collidable regardless of the tileset reference)?

Any help would be appreciated.

Hello BlueBird, and Hello Community, that is my first comment here on this board.

To get the Collisiondata from the tiledMap-Maps i have this little ExtensionMethod (quick and dirty) for you.

grafik
Fig1: From TiledMap Editor, here you can see some CollisionObjects


Fig2: When editing the TileSet you can add Rectangles to the specific Tile, and edit some properties of that Rectangle (on the left). In My Example i set the type to “WallCollider”

My WallCollider-Class

public class WallCollider : ICollisionActor
    {
        public IShapeF Bounds { get; set; }
        public void OnCollision(CollisionEventArgs collisionInfo)
        {
        }

        public WallCollider(RectangleF rectangleF)
        {
            Bounds = rectangleF;
        }
    }

The ExtensionMethod to get WallColliders from the Map-Data

 public static class GetWallCollider
    {
        public static List<ICollisionActor> GetCollisionActors(this MonoGame.Extended.Tiled.TiledMap map)
        {
            List<ICollisionActor> Result = new List<ICollisionActor>();

            int tiles_x = map.Width;
            int tiles_y = map.Height;
            int pixel_x = map.WidthInPixels;
            int pixel_y = map.HeightInPixels;

            List<(TiledMapTilesetTile, int start)> TileDefition = new List<(TiledMapTilesetTile, int start)>();

            int globalCount = 1;

            foreach (var tileset in map.Tilesets)
            {
                foreach (var tile in tileset.Tiles)
                {
                    TileDefition.Add((tile, globalCount));
                }
                globalCount += tileset.TileCount;
            }

            foreach (var layer in map.TileLayers)
            {
                foreach (var tile in layer.Tiles)
                {
                    var defintion = TileDefition
                        .Where(x => x.Item1.LocalTileIdentifier + x.start == tile.GlobalIdentifier)
                        .ToList();

                    foreach (var d in defintion)
                    {
                        foreach (var o in d.Item1.Objects)
                        {
                            if (o.Type == "WallCollider" && o is TiledMapRectangleObject)
                            {
                                var def = o as TiledMapRectangleObject;
                                RectangleF rect = new RectangleF(
                                    tile.X * layer.TileWidth + def.Position.X,
                                    tile.Y * layer.TileHeight + def.Position.Y,
                                    def.Size.Width,
                                    def.Size.Height
                                    );

                                Result.Add(new WallCollider(rect));
                            }
                        }
                    }
                }
            }
            return Result;
        }
    }

Some Explanation:
To get the correct Data, you have to itterate through every TileSet attached to the Map, an load every Tile from each TileSet. There you will find the Objects (WallCollider Rectangles).
Then you have to look at every Layer of the map, where the Tiles are used and then add a Rectangle with the specific Coordinates to your ResultSet.
The WallCollider-Class can than be inserted into the CollisionComponent from the Monogame.Extended-Framework, because it is implementing the ICollisionActor-Interface, although in this example the OnCollision-Method is empty.

Hint:
When looking into the Map-Editor Files with Notepad++ for example, you will see, that the Tile-IDs are incrementing over each TileSet used by a Map.
TileSet_A with 50 Tiles has ID 1 to 50
TileSet_B with 25 Tiles has ID 1 to 25
Within the MapData the IDs switch to 1 to 50 and 51 to 75 for A-Tiles and B-Tiles.
Be Sure to call this only once when loading a Map.

I hope that helps a bit. please excuse my english, and i am sure the above code can be optimized by alot.

Peter

Edit: Formatting, Typo

2 Likes