00:00
00:00
mike
hello!

Mike Welsh @mike

Age 39, Male

stupids

Penn State

San Diego

Joined on 2/24/00

Level:
23
Exp Points:
5,598 / 5,880
Exp Rank:
8,641
Vote Power:
6.47 votes
Rank:
Police Captain
Global Rank:
3,970
Blams:
1,268
Saves:
1,004
B/P Bonus:
16%
Whistle:
Normal
Trophies:
14
Medals:
916
Supporter:
10y 7m 13d
Gear:
1

AS2 style depth sorting in ActionScript 3

Posted by mike - December 19th, 2007


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.

see it in action
source

AS2 style depth sorting in ActionScript 3


Comments

what can l say nice

Sweet.

Maybe you should have them bounce off each other when they collide during the changing of depth.

Even though I complained about it in your last post, it is really cool that you use correct terminology and provide links to the term backgrounds in your posts...I've never taken a CS class, so I find it interesting to look into the theories behind what you're talking about. It amazes me how math can be so useful for logical operations, eg: using logs in the merge sort.

I look forward to future posts.

awesome

Looks awesome, I should use that for something :)

AS3 scares me aswell!

Depth sorting still boggles me. I wrote up what I thought was the perfect way to organize and sort movieclips for easy addition and removal, only to have something bizzare screw the whole thing up.

Still, it seems simpler than what you're describing and this review gives me more reason to stick with good ol' Flash 8.

good stuff man, hopefully this will make the as3 transition much easier should I decide to go that route.

any other AS3 snags like the depth sorting?

No idea what this means but I like it!

You're old.....
..........
..........
..........
..........
..........
..........
..........
..........
..........
22 years.....old :D

no offence but that is actually realy simple to do alls u have to do is make the smilies snaler as u go back...

that was cool

Mike <3

Fuckin saved. Though algorithims are scary.

Awesome!
Keep posting. Your posts are the most interesting of all the NG staff. ;)

nice work man, this is really helpful

It's nice to Google an ActionScript 3 article that's not just a total dump on the transition from AS2 to AS3. This wasn't what I was looking for, but a useful piece of information nonetheless. The link to the merge sort algorithm is a nice touch. Thank you so much!

Articles in the tone of Penquin11 or fetusdoctor's comments just bury the useful AS3 information out there. I think for my next comment, I'm going to go to a good graphic artist's article and write "No offense man, but drawing is real easy. Just put a circle for the head, a couple of lines for arms and legs, and you're done!", or better yet, "Gradients still boggle me. I wrote up what I thought was the perfect way to make colour fades pixel by pixel, only to have something bizzare screw the whole thing up.
Still, it seems simpler than what you're describing and this review gives me more reason to stick with good ol' Microsoft Paint."

thanx so much =) i use this now to swap depths according to y coordinates (the further something is down, the more it is in front)

function sortdepts(holder:MovieClip):void { //holder contains all movieclips to be ydepth.sorted
var len:uint=holder.numChildren;
for (var i:int=0; i < len-1; i++) {
for (var j:int=i+1; j < len; j++) {
if (holder.getChildAt(i).y>holder.getChildAt(j).y ) {
holder.swapChildrenAt( i, j );
}
}
}
}