Hi Daniela,
That’s a great question and a fun problem to think about. I don’t have experience doing it myself, so I can’t speak to what will actually work from a performance perspective, but here are some things to think about.
We know that the order in which your display objects render in Corona is based on the “painter’s model,” where the objects you create earlier are rendered before the objects you create later. You can then adjust the order by reinserting your objects into their parent groups using the :toFront(), :toBack(), or :insert() (with the optional index parameter) methods. Since your characters will be moving around the screen, it’s a given you’ll have to use these methods from time to time. I take it your question is when and how to do it most efficiently.
Looking at the perspective effect in Kingdom Rush, it seems like the “depth” is easy to define – objects that are higher up on the screen (low y coordinates) are “farther away” and should be rendered before objects that are lower down on the screen (high y coordinates), which are “closer”.
I think there are two broad approaches to trying to deal with this – “global” approaches that try to put *all* of your objects in the right order (even ones that aren’t overlapping, which means the render order wouldn’t actually make a difference visually), and “local” approaches that try to make sure any pair of overlapping objects are rendered in the right order (which is all that matters visually).
For the global approaches, some ideas would be:
-
A runtime enterFrame event listener. Each frame, the listener would build an array of all your objects based on their y-coordinate, sort it, and then loop through the now-sorted array and reinsert each object into the parent. For better performance, instead of doing this every frame you could do it every few frames (a user won’t really notice if it takes 0.2 seconds for an overlap to look right versus 0.033 seconds).
-
Similar to the first one, but instead of rebuilding and sorting the array each frame (sorting might be expensive depending on how many objects you have), you could predefine a depthField array. depthField would be an array, where each item represents a y-coordinate. Each item in the array would itself be an array that references all the display objects at that y-coordinate. Then, you could have an enterFrame listener on each object that, each frame, puts each object into the right array within depthField. Then you would loop through depthField and, for each sub-array of objects, insert those objects into the parent. The advantage of this is that the “sorting” happens implicitly by the index, so there’s no need to actually sort it every frame.
-
Create a different display group for each level of depth in your scene. At most, that would be one group for each y-coordinate, or if that’s too many, it could be one for every few pixels. Then, as your characters move, insert them into the appropriate display group based on the character’s y-coordinate. You could do that using an enterFrame listener on each object. Of course, a disadvantage of this method is that you can’t group your objects for other purposes (since an object can only belong to a single group
-
Same as any of the above, but instead of enterFrame listeners, use a metatable on each object so that it only does the work when the object’s y-coordinate actually changes
For local approaches, some ideas would be:
-
Make all your objects sensors using the physics library. Any time a collision is reported, figure out which object should be in front based on its y-cooordinate, and also check their indexes in their parent display group. If the indexes aren’t right, swap them
-
Same as above, but instead of using the physics library, detect collisions yourself using basic bounding-box or radius collisions
Anyway, I hope this gets your noodle cooking! Sorry if my ramble wasn’t completely clear in all cases, but I can try to elaborate or clarify where it’s helpful. I’ll also be interesting in hearing what others on the forum can suggest who may have more experience with this.