Tile map sprite rendering is broken in version 3 (at least 3.2)

Hello!

Our game uses tile maps and we render characters (sprites) nicely within the isometric map layers and tiles (a screenshot will follow below). So far, we are using version 2.2.3 and I recently started trying to update to version 3.2. I found there is a difference in the way the characters are rendered on the map and it is wrong in version 3.2.

Here is what it looks like with version 2.2.3. You can see that the squid is covered by the palm tree, etc. and it looks nice:

Now here is what it looks like with version 3.2. The squid still integrates nicely in the map but its transparent background is black:

Here are some details on how I place the sprites on the map:
 - The map has several layers, and I have set the cc_vertexz property to ‘automatic’ on all of them. This doesn’t realy matter in the end, as I set my own values (see next point);
 - I set the vertex z of each tile on the map myself, as the map is actually more complicated than the simple two-layers example and needs finer control. As you can see, it works fine (in 2.2.3), so there is no problem there;
 - I set the vertex z of each sprite I place using the same calculation that was used for the tiles, so that a sprite has the same vertex z (well, +1) as the tile it is standing on, which is essentially the same way the example works;
 - I set the z order of each sprite I place to a big number, so that it would be rendered after everything else around it on the map, and it would alpha-blend correctly.

I have seen the example for tile maps in version 3.2, I have also seen its code and that it works perfectly. However, there is one difference in my code, that has been neglected by the original author of the test - the sprite that moves in the test is actually a tile from the map and in my code, it is an actual sprite that is loaded separately. I have made the absolutely same test on my map - I made a tile from the map move around. That works fine. So, the problem seems to be that a sprite (that is not a tile) can not be placed on the map in version 3.2.

I haven’t dug too much in the code of cocos2d-x but my guess is that in version 2.2.3, the z order was used to order the draw calls, and it is not in version 3.2. In version 3.2, I think the positionZ property should be used to order objects for rendering from back to front but it seems it is not. It seems that my sprites are probably rendered before the layers of the map and alpha blending does not work.

This looks like a bug in version 3.2 (possibly in earlier 3.x versions too) to me. Please, if any of the developers sees this, comment on whether you could confirm they can reproduce that and whether it is really a bug. If that is so, I could re-post this in the issue tracker.

Cheers!

3.0 has a new rendering pipeline for sure.

http://www.cocos2d-x.org/docs/manual/framework/native/v3/new-renderer/en

Yeah, it does. That is why I’m guessing this bug was introduced with the change of the rendering pipeline. Any comments on whether the developers are aware of it? Are there any plans for fixing it?

There is a new FastTMX in v3.2. Can you tell me if it is possible for you to try that out and see if the problems persist? If so can file appropriate bugs

I have seen that FastTMX class but I haven’t tried it. I will test it as soon as I can and I will report the result.

Ok. I have made a better test, that does not use my code at all, and I tested both the regular and the fast tile map classes. Both maps break on this.

I modified the code of the tile map examples to use a sprite, that is not from the map’s layers. Here is a patch that can be used to test the issue:

diff --git a/cocos2d-x-3.2/tests/cpp-tests/Classes/TileMapTest/TileMapTest.cpp b/cocos2d-x-3.2/tests/cpp-tests/Classes/TileMapTest/TileMapTest.cpp
index 2eb4483..5dc01d9 100644
--- a/cocos2d-x-3.2/tests/cpp-tests/Classes/TileMapTest/TileMapTest.cpp
+++ b/cocos2d-x-3.2/tests/cpp-tests/Classes/TileMapTest/TileMapTest.cpp
@@ -1067,10 +1067,11 @@ TMXIsoVertexZ::TMXIsoVertexZ()
     map->setPosition( Vec2(-s.width/2,0) );
     CCLOG("ContentSize: %f, %f", s.width,s.height);
     
-    // because I'm lazy, I'm reusing a tile as an sprite, but since this method uses vertexZ, you
-    // can use any Sprite and it will work OK.
-    auto layer = map->getLayer("Trees");
-    _tamara = layer->getTileAt( Vec2(29,29) );
+    // Using a random sprite.
+    _tamara = Sprite::create("TileMaps/iso.png");
+    map->addChild(_tamara);
+    _tamara->setAnchorPoint(Vec2(0.5f, 0));
+    _tamara->setPosition(map->getLayer("Trees")->getTileAt(Vec2(29,29))->getPosition());
     _tamara->retain();

auto move = MoveBy::create(10, Vec2(300,250) * (1/CC_CONTENT_SCALE_FACTOR()));
diff --git a/cocos2d-x-3.2/tests/cpp-tests/Classes/TileMapTest/TileMapTest2.cpp b/cocos2d-x-3.2/tests/cpp-tests/Classes/TileMapTest/TileMapTest2.cpp
index bac5608…d91ccba 100644
— a/cocos2d-x-3.2/tests/cpp-tests/Classes/TileMapTest/TileMapTest2.cpp
+++ b/cocos2d-x-3.2/tests/cpp-tests/Classes/TileMapTest/TileMapTest2.cpp
@@ -1038,10 +1038,11 @@ TMXIsoVertexZNew::TMXIsoVertexZNew()
     map->setPosition( Vec2(-s.width/2,0) );
     CCLOG(“ContentSize: %f, %f”, s.width,s.height);
     
-    // because I’m lazy, I’m reusing a tile as an sprite, but since this method uses vertexZ, you
-    // can use any Sprite and it will work OK.
-    auto layer = map->getLayer(“Trees”);
-    _tamara = layer->getTileAt( Vec2(29,29) );
+    // Using a random sprite.
+    _tamara = Sprite::create(“TileMaps/iso.png”);
+    map->addChild(_tamara);
+    _tamara->setAnchorPoint(Vec2(0.5f, 0));
+    _tamara->setPosition(map->getLayer(“Trees”)->getTileAt(Vec2(29,29))->getPosition());
     _tamara->retain();
     
     auto move = MoveBy::create(10, Vec2(300,250) * (1/CC_CONTENT_SCALE_FACTOR()));

As you can see, the only change is that I am using “any Sprite” but it does not “work OK”.

Bug filed: http://cocos2d-x.org/issues/5753

Thanks for opening the issue!

I uploaded the patch for the test there.

Hi,

Me too upgrading framework from 2.2.5 to 3.2 and facing same issue :frowning:

We faced such issue in 2.2.2, that time we resolve it by applying kCCShader_PositionTextureColorAlphaTest shader.

But now same shader is giving some wired results like position and moving speed of sprites is changed.

Any help or update on this issue ?

@Anurag @lyubomirv
Basically, both implementation of cocos2d-x 2.X and 3.X are not correct, because all the children of SpriteBatchNode are executed in one glDraw call.
But when we want to use auto vertex_z feature and add a sprite with a manual vertex_z, what we want is to break the draw to 2 glDraw call to make the result correct.
Here is the comparison the the result in 2.x and 3.x
####2.x


####3.x

If we want to embed a sprite into a TMXlayer, we can only use the sprite from the tiles of the tilemap.

@dabingnn
So then, is this considered a bug or that is the intended way of working?

To me, using only sprites, embedded in the tilemap, makes no sense. That puts a limit of using only static images on the map and you would generally want to be able to animate those sprites. However, embedding all the frames for all animations as tiles in the tilemap does not make sense and is impossible to manage.

strong textpretty sure i was experiencing what dbginn is describing. it made me so confused about sprite sheets and their logical partitions when i was duplicating sprites ( minimally) between sheets and rarely if ever specifically calling the uncache/unload cache functions that i tried SDL for my last app. I miss the power of Cocos and thanks to threads like this can begin to appreciate it better again.