Easy depth sorting was one of the nice features of ActionScript 2.0. It was great to throw something onto depth 999999999 and forget about it. Isometric games had it easy -- just set each sprite's depth to its y position (or some function of it), and, woo, perfectly sorted sprites!
Sadly, Adobe strips this away from us in ActionScript 3. Depths are gone. Now your Sprites and MovieClips only get a list of children. The order of this list determines the order in which the children are drawn. You still get functions like swapChildrenAt(i, j) and setChildIndex( child, i ) to change the position of an object in the display list. Unfortunately, you can't supply any arbitrary value for i or j. You can only pass an index from 0 to numChildren-1 -- no more absent-mindedly throwing something to 99999, and no more setting depth simply to an object's y position.
The burden of sorting the display list is now the programmer's. Sure, it's a pain in the ass -- but here's where the magic of object oriented programming comes in! You can make a subclass of Sprite or MovieClip and add your own depth property to it:
class DepthSprite extends Sprite
{
private var _depth:Number;
private var _needsSorting:Boolean = false;
public function get depth():Number { return _depth; }
public function set depth(n:Number):void
{
_depth = n;
if(parent is DepthSprite) DepthSprite(parent)._needsSorting = true;
}
}
Now you can sort the display list based on the depths of the children, using any sorting algorithm you please! In my example, I use bubble sort.
protected function sortDisplayList():void
{
// sort my children based on their depths
// (bubble sort)
var len:uint = numChildren;
for (i=0; i < len-1; i++)
for (j=i+1; j < len; j++)
if ( DepthSprite( getChildAt(i) )._depth > DepthSprite( getChildAt(j) )._depth )
swapChildrenAt( i, j );
}
This homebrew depth system also has some big benefits over the old ActionScript 2 depths. For one, you can use floating point numbers for depths instead of integers. Also, you can safely assign two sprites to the same depth, and there will be no flickering (assuming that your sort is stable).
For the sake of clarity, I made the code as simple as possible. But it's slow -- crank the number of particles up to 200, and it starts to chug. There's a lot of room for improvement. Here are some big optimizations:
1. The example code uses a simple bubble sort. This is bad -- it's a slow and unstable sort. More efficient sorting algorithms, like merge sort, would be better.
2. There are lots of calls to getChildAt() and swapChildrenAt(). This actually causes a lot more overhead than you might think! You could store all the children DepthSprites in your own Array, sort the Array, and then rearrange the display list based on the Array. Even better, use a linked list!
3. There are lots of typecasts to DepthSprite. Not only does this cause a ton of runtime type checks, it assumes that all of the children will be a DepthSprite, which might not be true. This goes along with the above idea -- if you use a strictly typed linked list, you avoid the typecasts and you only work with DepthSprites.
q13qew
what can l say nice