Phaser: Support for external Tiled JSON Tilesets

Created on 7 Apr 2018  路  9Comments  路  Source: photonstorm/phaser

https://github.com/photonstorm/phaser/blob/d1f5f8a82b4a64d2a6a6a269e148232b51661a19/src/tilemaps/parsers/tiled/ParseTilesets.js#L35

I'd love to implement this feature and submit a PR. I am struggling with the basic lifecycle of loaded data sets. Could you give me any pointers? Would a new type of data set such as a 'Tileset' need to be created and exist prior to the Tiled parser executing so it could reference the external Tileset or something?

馃挅 Feature Request Medium

Most helpful comment

I left this open because I knew I was due to work on the Loader soon. This work has now been completed as part of the 3.7 release, and you can now do all kinds of nifty things with regard to manipulating the load queue dynamically, which should make this process a lot easier. You'll still need to mutate the tile data though, but parsing and loading external files is at least now possible.

All 9 comments

Feels to me like it should handle this in the loading stage, not the parsing. So when a tilemap json file is loaded and parsed, it inspects to see if it needs to load any external images and then adds them to the load queue.

Sounds good. Wouldn't it have to be loaded before any associated Tiled Maps, so the data is available when the Tiled Map is loading and setting 'tilesets'? Or would it be completely unassociated with parsing?

https://github.com/photonstorm/phaser/blob/f88489119b56171f3c37f781c5710b2828ac83e6/src/tilemaps/parsers/tiled/ParseJSONTiled.js#L57

That's the line I'm talking about.

https://github.com/photonstorm/phaser/tree/d1f5f8a82b4a64d2a6a6a269e148232b51661a19/src/loader/filetypes

  • Add a TilesetJSONFile type

https://github.com/photonstorm/phaser/blob/d1f5f8a82b4a64d2a6a6a269e148232b51661a19/src/tilemaps/Formats.js

  • Add a TILED_TILESET_JSON format

https://github.com/photonstorm/phaser/blob/d1f5f8a82b4a64d2a6a6a269e148232b51661a19/src/tilemaps/ParseToTilemap.js#L63

  • Figure out how to inject the tileset information at the right point?

Getting a little lost on the best way now... seems like adding external tilesets "the right way" might require quite a bit of refactoring?

It's certainly not a simple problem. Tiled's roadmap actually has a feature in the works for saving tilemaps with external data (object types, tilesets) as if they were embedded, though. See bjorn/tiled#1850.

This can semi-reasonably be implemented manually. I had this rigged up in Phaser 2 with the following process:

  • When map file is done loading, look for external tilesets and load them as JSON.
  • When tileset JSON is done:

    • Look for image reference and load it.

    • Mutate the original map data by replacing the tileset entry with the external data, keeping the firstgid field (kinda gross since really anything Phaser loads should probably be immutable). Make sure to remove the source property when merging the object or Phaser will throw because it bails out of parsing if source exists even if image and all of the other expected fields are there (ideally that warning case can be moved after the image case).

Complications:

  • In Phaser 3, listening to file complete isn't as straightforward. I ran into issues where the data wasn't actually populated in the file yet when the loader fired the 'load' event (maybe a bug?), but implementing a new filetype and overriding methods worked better.
  • In Phaser 3, the loader doesn't allow adding new files while it's running (addFile explicitly does nothing if the loader is running; I actually came here to ask for that to be changed when I saw this issue).
  • Built-in support for loading files referenced from other files seems complicated unless you make judgement calls around folder structure. Last I looked, Tiled JSON still references the files as .tsx with paths relative to whereever the tmx file was. It's not correct to assume that that's the case for exported JSON, so maybe it's best to leave that to the developer and instead make chainloading easier.

I think the solution I had for Phaser 2 was fine (mutating the map data is gross, but in Phaser 3 I already need to do that in order to split layers by tileset since apparently tilemap layers can have only one tileset), minus the loader issue, though I'd appreciate anything that makes this pattern easier.
I don't think embedding the tileset data in the map (whether manually or automatically) is the right solution for everyone because across many maps it's redundant, and it's harder for everything to stay in sync when using tile properties for game logic or whatever.

I did this for Phaser 2 as well, except it was as part of a Gulp task. And quite right, embedding on the client side isn't the right solution, but building a complete Tilemap once per build (or per save, as with the Tiled feature I linked above) is acceptable. It would still be nice not to _have_ to worry about this with Phaser though.

The complication you listed regarding not being able to queue files mid-loading would also be an issue for re-implementing asset pack files, which I loved to use with Phaser 2.

I feel like I need a shower after implementing it, but it's done. Thanks @hexus , @universal-cosmic-destroyer , @photonstorm !

If someone stumbles here and wants me to share the code with them just shoot me a line and I'll spend the time to clean it and put it up here...

@photonstorm We can close this if you'd like, as much as I would love to have this be supported directly in Phaser I'm fine with the hack job I did.

I left this open because I knew I was due to work on the Loader soon. This work has now been completed as part of the 3.7 release, and you can now do all kinds of nifty things with regard to manipulating the load queue dynamically, which should make this process a lot easier. You'll still need to mutate the tile data though, but parsing and loading external files is at least now possible.

Tiled (at least v1.4) has the following format:

"tilesets":[{
  "firstgid":1,
  "source":"terrain.json"
}]

Am I right in thinking the source field isn't supported yet? Or have I yet to find an example?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rootasjey picture rootasjey  路  3Comments

BigZaphod picture BigZaphod  路  4Comments

samme picture samme  路  3Comments

samme picture samme  路  4Comments

cncolder picture cncolder  路  4Comments