How to draw a 2.5D isometric platformer with VertexZ with many sprites

I’m writing a 2.5D isometric platformer, and from what I’ve read, having many sprites switching between ZOrders would cause performance issues. I’ve thought up a solution, but I’d like to get peoples input to see if there are any ways I could simplify things.


First, I have the normal problem of drawing multiple characters in front of and behind level sprites and eachother:

z0: + +    + +    +
z1: +    +  +     +
z2:       C
z3:       C
z4:   + +   +   + +
z5:  +  + +   + +
z6:          C
z7: +   + +    + ++

But on top of that, I have the problem of at least having ten of those layers on top of each other.

z2:  z4        z22
z3:  z5        z23
...  ...  ...  ...
z9:  z11       z29

(I increase by 2 because I have overlapping tiles.)

I thought of using VertexZ instead, because it should be faster as it’s handled by OpenGL, and I should be able to stay way under a thousand different values if I limit the display size, and there are optimizations I can put in later.

But then there’s the problem of the constant swapping of the VertexZ values. For example, whenever a character moved upwards or downwards, it would swap its z-value with the terrain or characters around it:

z1:  + +   + + +             C           
z2:      C         -->   + +   + + +
z3:  + +    +  +         + +    +  +

I can do that quickly with a linked list representing the vertexz numbers for the current layer,

However, if I were to jump, I would have to insert the character in the order it would end up at on the next layer up. (Now here’s from side view)

z3 z4 z5 z6 z7 z8 z9       z3 z4 z5 C  z7 z8 z9
z1 z2 z3 C  z5 z6 z7  -->  z1 z2 z3 z4 z6 z7 z8 

(notice the change in the bottom row)

I could do that quickly with a second, 2D linked list. Since each row of tiles would need to be able to point to the one above it regardless of where any characters were, the linked list would need to only contain terrain.

However, there’s the problem of inserting the character on the next level up and having to reorder the next several rows, and the rows on the lower layers. To fix this, I can insert gaps by only drawing terrain with even z orders at first, but then there’s still the problem of multiple characters on a single row, so I still have to keep the linked list idea.

There still might be a performance issue when many characters are standing side by side on a long horizontal line, but I’m not sure how I would fix that.


So that’s it. That’s my plan for drawing a 2.5D isometric platformer.

It seems like it’ll work, but it also seems like it’ll take a bit of effort to implement and debug. So, before I do that, is there anything that I could do to make that system simpler or better? Or, is there already a library that does what I’m talking about?

Actually, I think I got a fix for the many characters on a row problem: Instead of moving the next rows for the terrain down by vertexz, I’ll just have the gap in between allow for two sprites, and because collisions will never allow for a lot of sprites to be in the same location, I’ll just determine which sprites are in front of the nearest ones to the right and left

z0: terrain
z1: C  C C  C
z2:  CC C  C
z4: terrain

Yeah we do something similar. I highly recommend vertexZ for isometric maps. You set the static tiles vertexZ once and then only have to update it for dynamic (moving) objects. You can update only on change of position, or even only when position changes a given delta amount.

If you use the diamond isometric map formula for vertexZ = (tile.x+tile.y) or the TMXTileMap on vertexZ = -((MapW+MapH)-(tile.x+tile.y)) then you should be able to have many sprites within the same tile all separated based on their floating tile position. So an object at tile (5.3,6.4) would be in front of an object at tile (5.3,6.2) both of which would be in front of the tile itself (5,6), whereas a wall at every tile location might have a vertexZ offset of +0.95f, wall objects (torches,etc) might offset with .96-.99f. This leaves offsets .01f-0.94f for the dynamic moving game objects.

Also with a sprite on the exact same tile at the exact same spot probably it doesn’t matter what order you draw them in. And only in this case would you need to use your special ordering method you already have.

If none of your tiles or sprites need to render translucency (partial transparency) then you can batch them all if you use vertexZ into 1 draw call per texture.

The other option of course is to draw all tiles and objects as voxels without the back/bottom faces instead :smiley:

Huh, I don’t know why I assumed that vertexz would be an integer and not a float. I did work with opengl before after all…

I think I might set the characters to only use two of those decimal locations, like .25 and .75, that way I can give them multiple hats and stuff without worying. Then I can also give dropped items and effect sprites four places to go.

I’m pretty sure yours is simpler and therefore breaks less, but… hats…

Hmm, does tile transparency count as translucency? I have many tiles that aren’t pure squares, but they use alpha values to do that. Also, I’m setting it up so if the player’s character walks behind any wall or walks inside a building, the walls that would normally block the view should disappear, and that would probably mess with a voxel rendering method.

Anyway, for now, I think I’ll stick with the floating tile z location method and use whatever the default tile drawing methods after that are, because I need to get something simple working first.

Full transparent pixels in a non-square sprite are fine. Those are discarded by the alpha test shader.

However, if you want one “red” sprite to have opacity of 0.5 in front of a “blue” sprite that is behind it to blend with it to display purple pixels where they overlap requires them to be drawn in order from back (farther vertexZ/globalZ) to front (nearer vertexZ/globalZ).

As for hats, do what makes sense to you, definitely. In our characters we have 3-10 layers and each is .02f closer, for example, just fyi so however you want to set it up is great.

Oh, and while it shouldn’t matter the order of really close sprites you will want to hopefully have the vertexZ formula make sure that you don’t have identical vertexZ values in the same screen pixel. This will cause z-fighting. If you’re not familiar you can search google or these forums even probably and find out more.

Yeah, I’ve had z fighting problems before on a seperate project.

For things like windows though, I could use some old printing methods and make one pixel fully opaque, then the have the next two be fully transparent, then opaque, etc. :smile:

1 Like

guys can anybody share your code about sprite vertex z, i cant figure out how to do this