The one year game develpoment duel
Aug

18

2014

Handling Z-Index by Screen Coordinates

One problem that I ran into with my game was that my characters and images were not being properly z-indexed. For example, the dwarf in the image below looks like he’s pasted on top of the tree, even though his position on the map suggests he should be behind the tree.

zindex-incorrect

This is because in Corona, objects are z-indexed in the order that they are originally drawn to the screen. The dwarf was originally drawn after the tree, so he will always appear to be in front of the tree, regardless if he’s supposed to be in front or behind the tree.

What I did to fix this is add a couple of functions that run on every frame, loop over all the images, and re-draw the images ordered by their y coordinates.

https://gist.github.com/codepaladin/efa4c3b68ba5c110cdfa

What happens is that any image positioned further down on the y-axis should appear to be in front of any image that higher up on the y-axis. Since the tree has a lower y coordinate than the dwarf, the tree appears to be in front of the dwarf like this:

zindex-correct

Since the indexing functions runs on each frame, objects are correctly indexed as they move across the screen. The dwarf can move from behind the tree to in front of the tree and the objects will be drawn in the correct order to give the perception of depth.

4 of you did not hold your tongue!
  1. That's a great technique and I use Corona too, but haven't done this before myself. How does this work when it comes to using up the CPU since it has to reorganize so many objects?

  2. It's working for me so far, but I don't have a ton of objects on the screen. I have seen it slow down when I add some extra logic to the redrawing functions, though. I may end up not indexing the objects on every frame, but only when they really need to be indexed. For me, that means when characters are moving across the screen.

  3. Chris, First I would move your compare and table.sort functions "outside" of your enterFrame event and just call them once all the objects are loaded, calling these functions inside of your frame event is going to end up biting you in the butt :) Without giving you to much of a leg up on your brother I would implement something like this. function Reindex() for i = 1, #allImages do allImages[i]:toBack() end end function FrameLoop() Reindex() end function FinishedLoadingResources() local function compare( a, b ) return a.y > b.y end table.sort(allImages, compare ) Runtime:addEventListener( "enterFrame", FrameLoop ) end

    Call FinishedLoadingResources after you have loaded up all your objects, the reason for the function is so you can put anything else you need in there like timers etc. and don't declare a local function inside of frame event :) There are a lot of easier and faster ways to do this but if I wrote that code that would be cheating :) Christopher

  4. Thanks, Christopher! That makes perfect sense. I'm pretty sure you just gave me the edge I need to win this thing =)


Speak Freely


Thank you

Your comment will be published once it has been approved.

Click here to see the pull request you generated.