@Metric: I've just added glEnable(GL_ALPHA_TEST) to tests/SpriteTest in the zVertex example, and it works like charm!
TMXTileMap isometric zOrder ad-hoc sprite issue
(83 posts) (8 voices)-
Posted 1 year ago #
-
@riq: Great!
@matesbc: I haven't released the source yet. I ran into a few problems with how the current TMX map is being drawn.
The current TMX draw Method is drawing the map in a different fashion than a standard Isometric map. It seems to be drawing the X tiles from top left to bottom right, and the Y tiles from top right to bottom left.
Drawing this way causes conflicts with the basic principle of isometric maps, and the tiles are not being placed from left to right and top to bottom with an offset.
To elaborate further, OpenGL depth buffer can only handle values from -1.0 to 1.0 in the 2d projection. However, the 3D Projection can handle more, but in order for the vertexZ to work properly for both 3D and 2D it needs to be able to stay within -1.0 to 1.0.
The problem with the OpenGL depth buffer is that anything that gets infinitely close to 0 but doesn't reach 0 can not be properly sorted in the Z direction. Therefore it puts a limit on keeping the tiles layered from 0 to 1.0 in the vertexZ.
So, in order to properly sort the tiles and layers in the current arrangement of the TMX map causes some of the vertexZ's to get infinitely close to 0. Thus causing them to not overlap properly.
You see, I cannot allow the vertexZ to go over 1.0 not only to be compatible with 2D Projection, but also if it goes over 1.0 in 3D Projection the tile starts to stretch as it moves closer to the camera, which also makes it look bigger.
the formula for how the current TMX map format would be: zPosition * (1.0/(map.width * map.height)). The problem with this formula as mentioned before, causes some of the tiles to come infinitely close to 0. Which in turn causes the depth buffer to not overlap the vertexZ position properly with other tiles and objects. The zPosition starts at 1 at goes upward for higher layers.
In a regular isometric map that draws from left to right and top to bottom, you only have to worry about the height of the map and not the width. The formula for a regular isometric map is: zPosition * (1.0/map.height). Doing it the standard way allows for proper mapping of isometric tiles which stay in the 0 to 1.0 range and does not come infinitely close to 0. However, there is still a limit as to the height of the map with this method as well. The limit is 1.0e^-16, or in essence the limit of a 32bit float. Basically it would have to be a map with a height of 1,000,000,000,000,000 tiles. A lot yes, but I would stay in the range of 100 - 1000 tile height wise for the iphone hardware.
Also, if you were to put the TMX map in the left to right and top to bottom, the TMX map positions change because of the x offset on every odd y row. In turn, it causes the TMX map positions to be skewed and would not look like it was when created in TMX.
That is why, before I release the source, I am going to edit the Tiled QT editor and make it render the isometric tiles left to right, top to bottom, and offset the x position on every odd Y row. Good thing the Tiled Editor is open source and QT compiler is also LGPL or Commercial. Just give me a few more days and hopefully I will be able to share a new version of Tiled that renders the Isometric tiles in the standard left to right and top to bottom. When I release the new version of Tiled I will also release the new TMX Iso classes.
Posted 1 year ago # -
@Metric: I'm working with already existing tile maps retrieved from the server so if you don't mind I would like to give the classes a shot to see this weird behaviour as I can't quite realize what is going on (not because you haven't explained it perfectly clear but because I am pretty new at this) so if you don't mind emailing them to matsebc at gmail dot com , that would be awesome! thanks for the explanation, which I'll continue re reading until I can properly understand it
Posted 1 year ago # -
@riq: is it possible to re-think how cocos2d does it's z-ordering?
If we could just set the cocos2d z order for each tile on the map and have that be relative to all nodes, then we have a working solution. This could be accomplished with an array of all nodes sorted by z order.
Currently the z-ordering draws each child node by traversing the hierarchy (correct me if I'm wrong). Therefore, if the hero is a child of the map and the tiles are children of a layer which is also a child of the map then setting a z order for a tile doesn't work relative to the hero.
Is there anything wrong with trying out z-ordering based on a master array versus a node hierarchy?
That way we could set the z order for all the tiles on loading the map and dynamically set the hero's z order based on his y position.
Here's a code example of how to set all the z order for the hero and all the tiles:
// // we are inside a class called "Level" derived from CCTMXTiledMap // -(void) updateHeroZ:(CCSprite*)obj { int z = 10 + (mapSize.height * tileSize.height) - obj.position.y; [self reorderChild:obj z:z]; NSLog(@"Set z for %@ to %d",obj,z); } -(void) updateLayerZ:(CCTMXLayer*)layer { for(int y = 0; y < mapSize.height; y++) { for(int x = 0; x < mapSize.width; x++) { CCSprite* tile = [layer tileAt:ccp(x,y)]; if(tile != nil) { int z = 10+ (mapSize.height * tileSize.height) - ((mapSize.height - y) * tileSize.height) + (tileSize.height / 2); int t = [layer tileGIDAt:ccp(x,y)]; NSLog(@"%@ tile %d at %d,%d will have z %d", layer.layerName, t, x, y, z); [layer reorderChild:tile z:z]; } } } }Posted 1 year ago # -
@Riq: You can't have the 2D projection go higher or lower than -1.0 or 1.0 according to the documentation of OpenGL.
Almost have the new version of Tiled Qt ready with the new drawing view of isometric tiles. Will probably have it out tomorrow along with the new TMXIso classes.
Posted 1 year ago # -
@Metric - Just wanted to say thanks for helping to fixing this issue and re-doing the Tiled source as well! I love the iso-view and when I first saw it popup on cocos i got real excited, i ran into all the problems you describe and gave up on the project, but now with all this activity in the iso department, I can dust off that project and work on it again.
Earlier in this thread I asked Riq to confirm the draw order and he said it was left to right, top to bottom (which is what it should be). I have not had a chance to step through the code recently, but I do recall that the draw order was my problem when I first did some testing with it 5 months ago.
Posted 1 year ago # -
Here is the link to the new test project for the Isometric tiles. The zip also includes a new version of Tiled that allows you to switch between the original Tiled isometric view and to the new Isometric view in Tiled QT. You can find that option in the View menu.
This version of Tiled is only for MacOSX. I have yet to compile it for Windows, and I hope to compile it for windows. The source code is also included in the tiled-0.4 folder for QT.
the new CCTMXIsoLayer, CCTMXIsoTiledMap, and CCTMXIsoObject are located in the cocos2d source folder. If you plan to copy these 3 files to your project, then you need to do the following:
Put the 3 files in the cocos2d folder
Open up cocos2d.h and right after the original TMXLayer, TMXTileMap add new imports for the 3 new classes.For alpha and depth buffer to work properly you need to go into CCDirector.m. Goto the setDepthTest. Insert the following between glDepthFunc(GL_LEQUAL) and glHint():
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.0f);http://www.vantagetechnic.com/programming/iphone/IsoTileMap.zip
If you find any bugs let me know. I have tried to test these as best as possible.
Enjoy,
MetricPosted 1 year ago # -
If you are having problems downloading, do not worry. My dedicated server is currently being moved so there may be some downtime in the next few days. The server move should be finished by the 22nd of Febuary.
Sorry for the inconvience,
MetricPosted 1 year ago # -
@Riq: You can't have the 2D projection go higher or lower than -1.0 or 1.0 according to the documentation of OpenGL.
cocos2d uses
glOrthoand notgluOrtho2d.gluOrtho2duses, as you mentioned, -1/1 as the near/far parameters. But withglOrthoyou can use any value. I'll try it.Posted 1 year ago # -
@riq: Ah I see, yeah I must have been looking at gluOrtho2D and not glOrtho.
By the way I forgot to mention in the post about the release of the files. You need to call [[CCDirector sharedDirector] setDepthTest:YES] while setting up other cocos2d engine settings in your application after adding the two new lines to the setDepthTest.
You may want to also add [[CCDirector sharedDirector] setDepthBufferFormat:kDepthBuffer24]; or [[CCDirector sharedDirector] setDepthBufferFormat: kDepthBuffer16];
Posted 1 year ago # -
Awesome thanks for the files, missed somehow so if someone else following this thread grabbed them and wouldn't mind either posting a mirror or mailing them to me, I'll appreciate it.
Posted 1 year ago # -
fixed in r1805
Issue 780
http://code.google.com/p/cocos2d-iphone/issues/detail?id=780How to use it:
- Open Tiled
- I suggest creating at least 2 layers: 1 layer from the "grass", another layer for the objects. Create more layers if necessary
- Select the "objects" layer (NOT the "grass" layer), and add this property (always using tiled):
cc_vertexz=1cocos2d will add the correct vertexZ value to all the Tiled layers that contain the cc_vertexz=1 property.
It will also enableGL_ALPHA_TESTin those layers.VERY IMPORTANT: You also need to:
- the a depht buffer of 16 or 24 bits (NOT 0)
- set a 2D projection.For a working example see:
tests/TileMapTest.mand try the testTMXIsoZordertest.This is how a tmx looks like:
http://code.google.com/p/cocos2d-iphone/source/browse/trunk/Resources/TileMaps/iso-test-zorder.tmxI would appreciate if someone can update the TMX documentation with these changes:
http://www.cocos2d-iphone.org/wiki/doku.php/prog_guide:tiled_mapsPosted 1 year ago # -
@riq: is that update based on my code?
Posted 1 year ago # -
@Metric: No, but It is based on our discussion of using depth buffer + 2d projection + ALPHA_TEST.
The cocos2d wasn't changed too much. Actually the only thing that I added was the detection of cc_vertexz, and if present, it sets the vertex Z to the tiles.
This is the diff:
http://code.google.com/p/cocos2d-iphone/source/diff?spec=svn1805&r=1805&format=side&path=/trunk/cocos2d/CCTMXLayer.mI'm not sure if your code has more features or not. I like the way it is now, but I'm open to new ideas.
Posted 1 year ago # -
Riq,
First of all thanks for trying to improve this. I took a look at the new code you added - the problem I see is that the sprite initially appears behind the tree and then only when it hits the center it reorders the Z above the tree.
There is a solution to this issue without doing z-reordering - its simply drawing the tiles layer by layer in correct order and on the objects layer (trees,walls,etc) simply do a check to see if a hero is standing on a tile and then draw it in the same sequence it draws all the other objects. For a centered hero it only involves 1 "if" statement - if hero at center tile during object layer, draw it along with other objects. Is 1 "if" statement per character that needs to be drawn on a particular layer too expensive?
Posted 1 year ago # -
@shadaz: please take a look at my solution to the problem in the IsoTileMap test app I have put together. I just tested the link and it is working. Again the link is: http://www.vantagetechnic.com/programming/iphone/IsoTileMap.zip
It includes a new version of Tiled that can display the tiles in the standard fashion of left to right, top to bottom, and with an offset on every odd row.
The main classes that I created that do all the work are: CCTMXIsoTiledMap, CCTMXIsoLayer, and CCTMXIsoObject. The CCTMXIsoLayer draws the tiles from left to right, top to bottom with a offset on every odd row.
Posted 1 year ago # -
Metric, I'll give these clases a test today, I'll post back to let you guys know how it went, another unrelated question, any of you guy aware of an implementation of TMX that supports more than one spriteset per layer? (for cocos2d that is)
Posted 1 year ago # -
@matsebc: I know tiled can uses multiple sprite sheets per maps, but with cocos 2D you can only have one image on a CCSpriteSheet.
The only work around I can see is instead of using a spritesheet for the layers we just make the layer either a CCLayer or CCNode. Then load the image into a texture2d node and then create sprites that don't associate with a spritesheet. Instead, the sprites are still created with a texture and rect, but you will be able to have different texture2d nodes if stored in an NSMutableArray.
However, this method may take a performance hit since the sprites are no longer all rendered together at once, but instead individually. Though, it may not be an issue, because cocos 2d opengl doesn't render anything beyond the screen rect. So, in reality 1 layer of tiles would only have 15 tiles across if 32 pixels wide and in landscape mode, and 10 tiles up and down if tiles are 32 pixels high and in landscape mode. Just reverse the numbers for portrait mode.
@riq: if all the sprites are on the same CCLayer or CCNode, do they all render together, or is that only if they are on a CCSpriteSheet? If they do not render altogether if the sprites are on the same CCLayer or CCNode, then that is just wasting performance when drawing individual sprites not associated with a CCSpriteSheet. I imagine you could get better performance if the CCLayer or CCNode controlled the drawing of all sprites for that layer / node. Instead of having the sprites themselves draw each individually.
Posted 1 year ago # -
@riq the issue I have is that I cannot modify the generated map, because I get it from the server, and that map uses more than one tileset PER layer, as in each layer (or most) have GIDs belonging to more than one of the tilesets, so far I was just re pre parsing the map and generating a bunch of new layers, depending on the gid they were on, but not only this complicated things, as I ended up with a tmx map with 16 layers instead of 3, but now I have about 4 fringe layers (layers that are at hero level and have to place its tiles either above or below ) so I am now trying the oposite step, to create 1 spritesheet per layer, instead of 1 layer per spritesheet.
This reduces both textures loaded AND the number of layers on the map, not to mention I can work with metrics approach to tmx map as well as with yours.Posted 1 year ago # -
r1808 includes examples that uses both z-order (multiple layers) and vertexZ (uses depth buffer).
According to my tests, everything is working correctly. If something is not working Ok, please post an screenshot of the test, detailing what's wrong with the screenshot.
I'll ignore reports that doesn't have the screenshot with the expected behavior. In this particular case, it's much easier for me to understand a bug report with an screenshot.
Posted 1 year ago # -
@riq, apologies I wasn't trying to highjack the thread, cheers.
Posted 1 year ago # -
There were a few (but horrible) bugs in the samples. Fixed in r1815
I've also updated the programming guide regarding how to use vertexZ in the maps:
http://www.cocos2d-iphone.org/wiki/doku.php/prog_guide:tiled_maps#z_order_and_depth_bufferFeel free to correct any syntax/grammar error that you might find. thanks.
Posted 1 year ago # -
Thanks to @metric and @riq for their work on getting the vertexZ solution rolling. I am running into a transparency issue using r1828.
Whenever my hero character gets close to a tile with cc_vertexz automatic his "transparent" pixels override the correct tile and show the bottom-most TMX layer. Screenshots:

Working ok.
In the above screenshot the hero's vertexZ is -6.44 and the vertexZ of the rock directly above him is -7. There are only two tile layers in the orthogonal TMX, the ground "grass" layer with cc_vertexz -1000 and the rock layer with cc_vertexz automatic. There is an object layer with the player's start position above the rock layer.Why am I getting this transparency issue?
I've tried it in the simulator, on the device, with different depth buffer bit sizes, using different alpha pixel formats, and using different PNG file bit depths for my hero character, but I always get this transparency issue. By the way, yes, my hero character's sprite is a child of the TMX map object.
I remember @riq saying something about how this wouldn't work with sprites that are not completely opaque. Does this mean we can't use vertexZ with partially transparent sprites? Or is there something I am doing wrong in the code? Please point me in the right direction to solving this.
Note that the pixels that are displayed in the hero's transparent areas are always the bottom-most TMX layer, regardless of cc_vertexz value. For example, if I create one more empty layer below the ground/grass layer it will look like this:
Posted 1 year ago # -
@bullterburning:
Look at CCTMXLayer.m, line #628.// line 628 glAlphaFunc(GL_GREATER, 0.0f);and modify it with:
glAlphaFunc(GL_GREATER, 0.5f);If it doesn't work, try with different values from 0 to 0.999.
Let me know if it works.Posted 1 year ago #
Reply »
You must log in to post.