Isometric depth sorting


(Ashari) #1

hi, i am currently developing rpg-like game using libgdx.

i having problem in rendering moving object (sprite) when there are tall objects

i can handle it when the object is behind the tall object using layer order rendering (draw the sprites layer, then the tall object layer).

but, obviously if the sprite “must be rendered after” the tall object, it will produce something like this:

my current map layers:

  • collision (tile layer)
  • stage (object layer)
  • floor (tile layer)

“stage” object layer is where i put the sprites
"collision" tile layer is where i put the tall objects

after some searching, i know that i must sort it by their “depth”. but i have no idea how do it with tiled which i know rendering the map per-layer.

my current idea is creating two sprite layer (“below object” and “above object”) and then add-remove the sprites between that layers according their render order.

have other suggestion?


(Steffen Itterheim) #2

The usual way to go about this is by constantly updating each sprite’s draw order. For instance, in SpriteKit the zPosition property changes how a sprite is drawn relative to other sprites.

What you’ll need to do is:

  • find out how draw order of sprites can be changed in libgdx - there is hopefully some kind of “z order” or “draw order” or “depth” property
  • set the property based on the sprite’s y coordinate, or simply set it to the sprite’s Y coordinate (you may need to inverse it though depending on whether positive or negative z order makes sprites come out in front of others)
  • update this property either every frame, or whenever the Y coordinate changes (ie during movement) - the latter is preferred if most of the sprites do not move most of the time

This will ensure proper depth sorting of the sprites with the map but also with other nearby sprites.


(Ashari) #3

thanks for the reply,

it works to ordering my sprites :smile:
but, actually i think the “z order” only work when rendering things in same layer.

in my main render:

render(){
  ...
  map.renderFloor();
  map.renderStage();
  map.renderCollision();
  ...
}

so, even if my sprites rendered nicely, it will be overlapped by next layer.

well, it’s the tiled renderer in libgdx. :’’)


(Steffen Itterheim) #4

Right, the layers. In Cocos2D and SpriteKit there are modes where the whole node hierarchy is ignored when it comes to draw order. In Cocos2D this would be the vertexZ property. In SpriteKit it’s simply enabling a depth-sorting mode (a flag on the view or scene). Maybe, just maybe libgdx supports something like that as well?

If not, you’ll probably have to bite the bullet and move sprites from one layer to another. Hopefully this doesn’t add too much overhead.


(Thorbjørn Lindeijer) #5

Moving sprites between layers may not get you far, because the sprite may need to be both in front as well as behind different tiles on the same layer (like in a corner of a room). So you generally really need to solve this by either using a Z-buffer (that doesn’t work well with partial transparency, but you don’t seem to have that) or making sure that the draw order is correct, which means interleaving the rendering of tiles with the rendering of sprites.

I personally also don’t know whether libgdx has any convenience for this. You may need to implement some custom rendering logic (which really shouldn’t be that hard).


(Ashari) #6

well, as far as i know libgdx didn’t support that when rendering tiled map :’’


yes, you’re right ._.


i think i will follow bjorn advice to interleaving the rendering of tiles.
thanks guys.


(Ashari) #7

did it :smile:

just changing from:

for(layer in layers)
    for(row in rows)
       for(col in columns)
         //render method

to:

for(row in rows)
   for(col in columns)
      for(layer in layers)
        //render method

just a little problem in dragon’s leg :sweat_smile:
can be solved by render the lowest layer first

the code for libgdx user: