I’m not quite sure how I want to transfer maps from Tiled to my game engine. I’d like to 1. use different tile sets, and 2. make it easy to add tiles to each set in the future as well.
It seems ideal in a game that you’d be able to make one tile set = one asset package that could be loaded / unloaded from memory as needed. For instance I can have a “Castle” package of 100 tiles and a “Forest” package of 80 tiles, and whatever for other locations, and if I wanted a scene that used both then I’d load both (even if a list of references persists).
But either having different packages loaded at the same time or modifying these tile sets / packages as you develop introduces problems in the pipeline.
If the game loads “Forest” first before “Castle” then whatever index ID’s the map file had are now for a completely different set.
And even if I did make it so that packages loaded in a particular order / place Tiled still treats each texture set as a continuation of the last in the map view (the “first” id). So when I add new tiles to a set earlier in the index it changes ALL the map ID links to the next set. If I add a tile to “Castle” to make 101 tiles then all “Forest” tiles are off by one in the map file.
Am I missing something or is there a way to have different tiles retain their “tileset” ID when referenced by the map? Maybe being on a different layer? Is there a way to export a different map array for every tile set? Or an array that points to which set the individual index points towards?
Different tilesets have different global tile IDs. So, “forest” could be tiles 1-256, and “castle” could be 257-512, for example. Within the tileset they’re numbered locally for consistency and ease of reference, but each tileset has a “firstgid” (first Global ID) field that denotes the offset of the tiles as used within the map. To know which tileset a particular tile in your map is using, you’d just need to look at its ID, and compare it to the firstgid fields of your tilesets.
These global IDs are per-map (at least currently; perhaps the upcoming Projects feature will change this), so a map that only uses the “castle” tileset will refer to its tiles as 0-255, while a map using both “forest” and “castle” might refer to castle tiles as 256-511. In your game, you only need to load those tilesets that are actually used. As long as your parsing of Tiled maps is correct, there should be no problems with load order or changing tilesets*.
* Tiled numbers tiles within itself going from the top left in rows, starting from 0. To go from a global tileID (such as you’d fine in the map) to the local ID, you’d find which tileset it’s from, and then subtract the firstgid from the global ID. If you append tiles to the end of a tileset and don’t change the image width and only extend the height, the coordinates of all existing tiles will not change. If you need to make the image wider, that will offset the tile IDs and will break tile references in maps using them. This can be remedied via a custom script (if you know the original width and the new width, the mapping from old tile IDs to new ones is trivial), but Tiled does not provide a built-in feature to deal with this currently.
I guess then what I should have asked then is if there’s some kind of “project” file to go along with map files and tile sets but that’s not implemented yet? Something that holds links, display options, and what the global id is for each set?
Just to be clear: Right now it seems if I want multiple maps that use the same ID list I need to have the same tilesets linked to every map file even if that map doesn’t use that tile set so that the global IDs are the same. And if I change the tilset then I have to open every map file and re-export it, or at least open them so they can see the tileset again?
The .tsx file (or .json tileset file if you use that option) contains the image reference, and any other information about the tileset. If you choose to embed tilesets (not recommended for larger projects), then that information would be in your .tmx file (or .json map file if you use that option).
The map (tmx/json) file contains the firstgids for each tileset. If you open up a TMX file, you would see something like
This means that tile with global ID “40” in this other map would be a different tile in a different tileset than on the other map, but that doesn’t matter, because either way, you have all the information you need to render the tile and get metadata for it.
You’re right that if you want the exact same IDs in every map, you’d need the same tilesets linked, but there’s no point in doing that because you can easily get the tileset and local ID for each tile. There’s no need for your maps to have the same global IDs.
If you change your tileset in such a way that the old tiles’ IDs are not affected (i.e. only append to the end instead of rearranging and don’t change the width), you would not need to do anything with older maps, you wouldn’t even need to open them up again. Tiled doesn’t know (or need to know) about the contents of your tileset images, it only deals with coordinates on the image, and those only really depend on the width of the image.
If you do need to change your tilesets in such a way that affects the old tiles’ IDs (i.e. rearrange them, or change the image width), then you would need to write a script to update all the old maps ): I’m hoping eventually Tiled will get a feature or plug-in to make this easier.
The way you do things, the game makes a single array of tile objects to be filled and when the level changes you’re reading the XML and changing the string paths that each tile object in the array points to, and then they’re loaded?
I was originally thinking of just making an array for each texture package with references to tile objects at runtime, including the path, and then when the level needs it create the texture asset as a pointer within the array. Alternately I was exploring one giant array of tile objects and loading the required tiles in chunks. Getting the index ID’s to line up was not easy though.
I was thinking that because I have this habit of making ALL the references to assets I’ll need at runtime in so I always know where and what they are. Then load as needed. I’ll have to re examine my setup some more I guess.
Will be looking forward to that project update though.
To avoid re-reading tileset files, you could read in all the tileset data (tileset sizes, animation data, per-tile collision data, etc) at startup and keep that in memory, and then you’d only need to read the TMX (map) files as each level is loaded, and point to the correct tileset object in memory as needed, with the firstgids set correctly, and load/unload textures as needed (or load them all up at the start if you have the memory for it).
“Tile objects” have a specific meaning in Tiled (Objects which use a tile as their sprite), but it sounds like you mean something else?
Note that this is not entirely accurate. The mechanism Tiled has for this is not perfect, but it can deal with this in some situations. If Tiled detects that the width of a tileset changed and that this affects the number of tile columns, it prompts the user about whether he wants to fix up the tile references. This can affect tile references both on a map and within the tileset (because also the local IDs changed).
One problem with the current implementation of this is that after that prompt Tiled will forget about the change in tile columns and when you then open further maps using that tileset it will not prompt again even if those maps would need to be adjusted as well. The only way to work around this problem currently, is to first open all affected maps in Tiled and only then change your tileset image (while having live reload enabled). In that case, Tiled will (or should, it’s not tested very often…) fix up all those maps.
Fortunately changing the width of a tileset image is a relatively rare operation…
Definitely it would be nice to ship a custom tool or built-in action that can fix up maps and tilesets after tiles have been rearranged on the image. I imagine for this the tool would need the old tileset image and the new tileset image, so that it can detect which tiles have been moved. Precondition is of course that only rearrangement took place, and no modification.