I looked around, and the only solutions I found for sorting children of displayGroups involved copying everything out, sorting, then replacing. Also, they seemed to sort by the Y coordinate, which doesn’t work for me.
So I wrote a function that sorts the children of a displayGroup without copying in and out, that takes advantage of the general stability of the collection from frame to frame, and that sorts by Z.
[lua]displayGroup.sortZ = function(self)
local lowerBound, upperBound = 1, self.numChildren
local sortedMaxZ, index = self[lowerBound].z or 0, lowerBound + 1
while index <= upperBound do
local testItem = self[index]
local testZ = testItem.z or 0
if testZ < sortedMaxZ then
local lteIndex = index - 2
while lteIndex > 0 do
local lteZ = self[lteIndex].z or 0
if testZ >= lteZ then break end
lteIndex = lteIndex - 1
end
--printf(“Moving %i to %i”, index, lteIndex+1)
self:insert(lteIndex + 1, testItem)
index = index + 1
elseif testZ > sortedMaxZ then
local gteIndex = index + 1
while gteIndex <= upperBound do
local gteZ = self[gteIndex].z or 0
if testZ <= gteZ then break end
gteIndex = gteIndex + 1
end
if gteIndex - 1 == index then
--printf("%i is already in place", index)
sortedMaxZ = testZ
index = index + 1
else
--printf(“Moving %i to %i”, index, gteIndex)
self:insert(gteIndex, testItem)
end
else
--printf("%i is already in place", index)
sortedMaxZ = testZ
index = index + 1
end
end
end[/lua]
I’ve tested it quite a bit, so I’m fairly sure it’s bug free. If a child does not have a Z field, it is presumed to be 0. The implementation is basically a bubble sort, since it is easy to write, easy to understand, and performs well when the collection is already mostly sorted. Also, this sort is stable, whereas anything run through table.sort is not guaranteed to be so.
I have this function run every frame after all input and timing events have completed. It’s quite nice to set the Z field of any child and have its render order handled automatically. What’s really handy, though, is that now I can tween depth.
In the Windows simulator, the CPU hit for the below example was not noticeably different than with the sorting turned off (both clocked in around 0.3% CPU usage). Here is an example of it handling faux 3D card animations: