I've been trying to organize my layers into groups using Tiled 1.2.0

However these groups are being ignored by the Tiled parser
The parser looks for layers of type "tilelayer" and ignores the rest. My "Platform" element is of type "group". As a result, this.layers is populated only with the layer "Ground" in this example
The JSON structure of the example above :
{ "height":30,
"infinite":false,
"layers":[
{
"data":[...],
"height":30,
"id":1,
"name":"Ground",
"opacity":1,
"type":"tilelayer",
"visible":true,
"width":40,
"x":0,
"y":0
},
{
"id":2,
"layers":[
{
"data":[...],
"height":30,
"id":5,
"name":"Platform",
"opacity":1,
"type":"tilelayer",
"visible":true,
"width":40,
"x":0,
"y":0
},
{
"data":[...],
"height":30,
"id":6,
"name":"Platform-grass",
"opacity":1,
"type":"tilelayer",
"visible":true,
"width":40,
"x":0,
"y":0
}],
"name":"Platform",
"opacity":1,
"type":"group",
"visible":true,
"x":0,
"y":0
}],
"nextlayerid":7,
"nextobjectid":1,
"orientation":"orthogonal",
"renderorder":"right-down",
"tiledversion":"1.2.0",
"tileheight":16,
"tilesets":[],
"tilewidth":16,
"type":"map",
"version":1.2,
"width":40
}
The relevant line : l30 in /src/tilemaps/parsers/tiled/ParseTileLayers.js :
if (json.layers[i].type !== 'tilelayer')
{
continue;
}
I think that the group properties have to be passed on to the nested layers in the following way :
child_opacity *= parent_opacitychild_visible = child_visible && parent_visiblechild_x += parent_xchild_y += parent_yDid I forget any property ?
The new code should probably use a recursive loop to go through the different levels of nesting (groups inside groups)
I can work on a PR if you want
Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.
Sometimes it's nice to have different groups that contain layers with the same name. For example you might have two groups, "overworld" and "underground", that each contain a "background" layer. I propose prepending group names to layer names. So in this example you'd end up with one LayerData with the name "overworld/background" and another with the name "underground/background". That way you can do things like tilemap.createStaticLayer( group + '/' + layer ).
UPDATE: well there are LOTS of tilemaps in the phaser3 examples with their TMX files and those have served nicely. I don't believe any of them use groups (I didn't look exhaustively) but it was easy enough to just add some groups to an existing one.
Does anyone have some example Tiled maps that have groups? Is there just a good set of general example Tiled maps online? I'm working on this and need some test data.
I'm going to look around the Phaser examples for a few good tiled tilemaps but I'm assuming they won't have groups going on and that the original TMX file will probably not be there (just the JSON).
I have been working on this and have a reasonable implementation that accounts for groups rather than skipping them. Here are some subtleties:
A Tilemap game object has no sense of hierarchy for its stored layers (they are in a flat array) and changing this is out of scope. Instead, I think it is best to flatten that hierarchy and discard the groups as they are parsed.
Applying the inheritance of opacity and visibility as suggested by Babeetlebum works well and causes the layers to mirror their behavior in the Tiled editor.
child_opacity *= parent_opacitychild_visible = child_visible && parent_visibleI also had to be careful to look for offsetx and offsety (and presumably startx and starty for infinite maps) and account for these in computing the layer x and y. Note, I haven't tested with an infinite map to confirm the change in property names for offset, I'm just assuming based on how the tile layer parser already handles infinite maps.
child_x += parent_x + parent_offsetx + parent_startxchild_y += parent_y + parent_offsety + parent_startyRenaming layers as suggested by jbpuryear makes sense because layer names can act as unique IDs in phaser and flattening the hierarchy would create collisions. In order to help programmers that don't expect this renaming, I modified the Tilemap object to output a list of valid layer names when one is requested and not found. This way, they will see the group names included with the layer name on the console and have a prayer of figuring out what is wrong.
child_name = parent_name + '/' + child_nameIn order to avoid breaking maps that don't use groups, I do NOT append a '/' for the implied root group.
Tiled lets any layers exist inside of groups (object and image layers included) so I modified the parsers for all three layer types to account for this. All behave as above, inheriting the properties as suggested and re-naming to include group names. This was trickier with object layers because the X and Y values are baked into the objects rather than stored in the layer but I think I have it correct.
I duplicated the features test map and added a bunch of group layers to it to test inheriting all these properties and having all three different kinds of layers in groups. So far, all seems to work as expected and none of the previous tilemap examples have broken.
I'm going to keep testing a little bit more with the phaser3-examples as this was a pretty significant change in the end, but once I've kicked the tires and all seems okay I will make a pull request for this issue. When updating documentation, I have assumed this will be a part of 3.21.0 (just for the sake of putting something in there).
When I tried this out with an infinite map, things got complicated! Near as I can tell, infinite maps were not quite correctly implemented even for maps without group layers. There are two key properties related to position for a tile layer:
_startx/y_ are documented in the Tiled 'latest' 1.3 beta manual but they appear in JSON output even with earlier versions of tiled (I am using 'stable' 1.2.4 and they show up). They were being accounted for already in ParseTiledLayers if the map was infinite.
_offsetx/y_ have been around for a long time and can be controlled right in the Tiled interface. I think they are not frequently used but they do need to be accounted for when importing. ParseTiledLayers does so for NON-infinite maps but it seems to ignore them for infinite maps which is NOT correct. Those values can be there regardless of weather the map is infinite or not.
Once I realized that and fixed this (and after a lot of monkeying to get things in the correct units) I got the group layer code to work with both bounded and infinite maps. At this point I think the code is ready. I will clean things up and put out a pull request soon!
On another note, I'm wondering if I should also offer a pull request for my new tests? I built them on top of the phaser3-examples repo but they really aren't 'examples' but are just tests to make sure the changes still work. I just duplicated the features-test map a couple of times and added groups for one and toggled infinite map for the other.
Thank you for submitting this feature request. We have implemented this and the feature has been pushed to the master branch. It will be part of the next release. If you get time to build and test it for yourself we would appreciate that.
Most helpful comment
Sometimes it's nice to have different groups that contain layers with the same name. For example you might have two groups, "overworld" and "underground", that each contain a "background" layer. I propose prepending group names to layer names. So in this example you'd end up with one LayerData with the name "overworld/background" and another with the name "underground/background". That way you can do things like tilemap.createStaticLayer( group + '/' + layer ).