cocos2d/cocos2d-html5

Isometric tilemaps are broken

mateosss opened this issue · 7 comments

CCTMXLayer.js getTileAt bug at line 427, bad vertexZ value

in https://github.com/cocos2d/cocos2d-html5/blob/develop/cocos2d/tilemap/CCTMXLayer.js#L427

the value of vertexZ is always being 0, so when you use this method, the selected tile changes its original Z order.

here is the diff between the last version I used that worked, in this one it uses the _atlasIndexForExistantZ function that has been removed.

@pandamicro I invoke you, after all you commited that 😬

Please, any response would be nice, the fact that the tiles changes their zIndex when using a get function is really weird, and it brokes the tile map completely. Right now, isometric tile maps behaviour is broken if you are using this function (which you probably are if you are already using these kind of maps).

Sorry @mateosss , I wasn't noticing your issue report because this repo wasn't in active maintenance, our team mainly focusing on Cocos Creator now

Actually, my PR almost rewrote the TMXLayer, the purpose was to improve performance of it and enable dynamic culling of tiles. Instead of using Sprites inside a SpriteBatchNode(TMXLayer), I'm using pure data which is then rendered directly by the render command. If we use the old way, it won't be possible to culling big maps, then TMXLayer is hardly useful for big maps. And SpriteBatchNode is using too much memory with V3F_C4B_T2F_Quad, the calculation performance is also relatively low.

I also removed most data types in old design, including _atlasIndexArray, the behavior your are seeing is actually for placing dynamic tiles (get from the map) correctly. Before get from the map, a tile is pure data with pos and gid information. After get, it's becoming a separate Sprite, which won't be rendered inside the map. To render it correctly, we are using vertexZ as its real purpose, the z depth, and activating depth test will allow us to pass separated tile draw call after the map draw call, but be rendered inside the map. So vertexZ must be set with its location information.

Please see our test case for how to set correct vertexZ in the new design:

https://github.com/cocos2d/cocos2d-x/blob/v3/tests/js-tests/src/TileMapTest/TileMapTest.js#L1120

Sorry for the inconsistency and inconvenience.

Okay, thanks for the response.

I will see that test case and write here what are the changes I should have made for it to work.

Thanks again, and sorry for the repeated messages and the "clickbait" title but this kind of undocumented things are a pain in the ass while developing.

I'm sorry about the undocumented changes

I will try to be sure that this is expected behaviour before proceed, this is the tilemap:

a

And this is the tilemap after I execute this.getLayer("Background").getTileAt(tileCoord); with tileCoord being the coordinate of the tile that is being brought to the front.

b

If I understand correctly from what you wrote, I should manually modify the vertexZ (which I think is the same as the zIndex of the tile) to be like

this.tamara.vertexZ = layer.vertexZ + cc.renderer.assignedZStep * Math.floor(30 - this.tamara.y / 32) / 30;

as it is writen in the test case, where this.tamara would be my tile (which I will have after calling getTileAt which in turn will already change the tile zIndex/vertexZ), which seems to be like a pretty weird ugly fix that is not working for me, I am getting the same results as before (like in those images), even though it seems to be affecting the tiles zIndex or vertexZ (if I put a high constant value (>3000) the tile disappears). So this formula/weird fix doesn't seem to be working in my tilemap.

I should point out again, that all these problems are happening because of calling getTileAt, which in turns calls _vertexZForPos which tries to enter an if by evaluating the expression this._useAutomaticVertexZ that is being false in my game, I suspect that that property should be true but even if I hardcode a true in that if statement, the result is still modifying the tilemap's look (a.k.a not working).

Just to let anyone know, I found a workaround for this by duplicating the layer in the tmx file, so when getTileAt is called, it moves the zIndex, but it is occluded with a copy of itself so it is not visible to the player. Pretty dirty trick, but it does the job.