Forum Topic: As3: Display List & Swapping Depths

(4,917 views • 11 replies)

This topic is 1 page long.

<< < > >>
None

ShooterMG

Reply To Post Reply & Quote

Posted at: 5/9/07 10:11 PM

ShooterMG EVIL LEVEL 03

Sign-Up: 11/10/06

Posts: 266

Swapping Depths in AS3 is a frequently requested technique, and it is ridiculously easy to do.

In AS3, there are two components. The Virtual Machine, and the Rendering Engine. You must create objects in both places in order for them to be displayed on the screen. This is not as complicated as it sounds. In fact, it's easier than in AS2.

The rendering engine contains something called a Display List. Each .swf only has one display list, and if you want your object to display in your movie, you must add it to the display list. Only Display Objects can be added to the display list. MovieClip, Sprite, Shape, TextField, etc. are all extensions of the DisplayObject class. Only objects that are extended from this class can be added to the display list.

Firstly, create a new display object:

var mySprite:Sprite = new Sprite();

You have just created a new sprite object. Think of a sprite object as being a MovieClip without a timeline. So now you have your object (pretend we have graphics in it). Just because you created the object, that does not mean it will display in your movie. You must add it to the display list.

addChild(mySprite);

This adds mySprite to the display list. Now your object will be seen on the screen in your movie.

OK, but what about depths? Depths are automatically handled by the rendering engine. When you add a child to a display object container ( i.e. the stage, or other objects that contain display objects), it is adding the object to the next highest depth. So if you have 5 MovieClips on the stage, and you add another one, it will be in position 5 (0 is the lowest position).

A common myth that I am hearing is that you have no control over this. This is false, and I will show you how to control your depths. Say you have 4 MovieClips in the display list.

Score – 3
Enemy – 2
Player – 1
Background – 0

I have listed these clips in the order in which they will appear on the stage. The background, being at position 0, will be underneath everything, whereas the score will be above everything. Now say you want your player to shoot a gun.

addChild(Bullet);

The list would now look like this:

Bullet – 4
Score – 3
Enemy – 2
Player – 1
Background – 0

This is fine and dandy, and perhaps awesome. Less work than attachMovie. Well, what if you want the bullet to appear above all the characters, but have it go behind the score so it doesn’t look weird? AS3 doesn’t let you specify depths.

Wrong. Do this instead.

addChildAt(Bullet, 3);

What this does is it adds the bullet to the display list in the specified index location 3. This causes the existing object at the desired location, and all objects above that location, to be shifted up by one. So this is what the display list would look like:

Score – 4
Bullet – 3
Enemy – 2
Player – 1
Background – 0

Notice the score movieclip is now at index 4. It was shifted up, and it now is displayed on top of everything, so the bullets will go behind it. Nice, huh? So now say you decided that after all of this, you want the Player character to display above the bullets, because he’s invincible to bullets and they should just pass behind him. But how do you change an objects index location once it’s in the display list?

setChildIndex(Bullet, 1);

Doing this will change the bullet’s index value from 3 to 1, causing the object already at index 1 to shift up, along with everything else.

Score – 4
Enemy – 3
Player – 2
Bullet – 1
Background – 0

Fairly simple. But I already know what you’re going to ask next. “But hey, how the heck am I supposed to know the index numbers?” AS3 has a simple method to do this for you. You don’t need to know the index value of the bullet, because that’s the object you are moving. What you need to know is the index value of the spot you are moving the bullet *TO*.

getChildIndex(Player);

This will return the index value of the Player movieclip, which was 1. But how do you actually use this? Like so:

setChildIndex(Bullet, getChildIndex( Player ));

This sets the Bullet to the index that the Player is at, and then shifts the Player and everything else up by one.

So now the moment of truth. To “swap” depths, you use the techniques I have shown you. Here is a simple snippet that you can use in your movies to swap depths between two display objects:

var a:int = getChildIndex( object1 );
var b:int = getChildIndex( object2 );

setChildIndex(object1, b);
setChildIndex(object2, a);

Boom, their depths have been swapped.


None

Alphabit

Reply To Post Reply & Quote

Posted at: 5/10/07 12:05 AM

Alphabit NEUTRAL LEVEL 09

Sign-Up: 02/14/06

Posts: 4,077

At 5/9/07 10:11 PM, ShooterMG wrote: var a:int = getChildIndex( object1 );
var b:int = getChildIndex( object2 );

setChildIndex(object1, b);
setChildIndex(object2, a);

Or you can just use
swapChildren(object1,object2)

or if you want to swap two objects at a certain depth, but you don't know their name... You can use something like:

swapChildrenAt(0,1)

^ Where 0 and 1 are integers specifying the depths of each object.

Cheers :)

BAM! IN YOUR FACE!
My NEW blog: http://jonsworkblog.blogspot.com/
Current Project: http://modset.net/physicsb.html


None

ShooterMG

Reply To Post Reply & Quote

Posted at: 5/10/07 12:11 AM

ShooterMG EVIL LEVEL 03

Sign-Up: 11/10/06

Posts: 266

Hey, it's the journey, not the destination ;)


None

Rammer

Reply To Post Reply & Quote

Posted at: 5/14/07 06:24 PM

Rammer DARK LEVEL 32

Sign-Up: 06/08/03

Posts: 4,327

At 5/10/07 12:11 AM, ShooterMG wrote: Hey, it's the journey, not the destination ;)

and both paths were awesome.

excellent tutorial. you explained every kind of question i came up with while reading this.

snyggys


None

Kinsman

Reply To Post Reply & Quote

Posted at: 5/14/07 06:49 PM

Kinsman NEUTRAL LEVEL 14

Sign-Up: 07/15/00

Posts: 137

I'd like to add that the display can be an entire tree, not just a simple list - you can manage depths more easily with a technique like this.

// Set up two empty movie clips.

HUDLayer = new MovieClip();
GameLayer = new MovieClip();

// Add them to your stage, or whatever you're using as the main movie clip, so that the HUD's layer is on top of the game's layer.

addChild(GameLayer);
addChild(HUDLayer);

// Now, add some of your custom objects to the layer of choice. All objects in the HUD layer will be on top of all objects in the game layer.

HUDLayer.addChild(new ScoreDisplay());
HUDLayer.addChild(new LivesDisplay());

GameLayer.addChild(new PlayerShip());

BBS Signature

None

greystone227

Reply To Post Reply & Quote

Posted at: 3/7/08 10:01 PM

greystone227 LIGHT LEVEL 09

Sign-Up: 07/28/07

Posts: 39

Here's some code for those of you missing the getNextHighestDepth() function. Keep in mind that if you're just adding an object to the display list, you don't need to do this as it automatically goes to the highest available depth. This is only necessary if you want an object to always stay on top even after it's added to the display list (say, a ship after you add bullets to the stage).

//This goes in an ENTER_FRAME function

if (getChildIndex (box) < numChildren - 1)
{
setChildIndex (box, numChildren - 1)
}


None

oreidoouro

Reply To Post Reply & Quote

Posted at: 5/15/08 01:45 AM

oreidoouro NEUTRAL LEVEL 01

Sign-Up: 05/14/08

Posts: 9

is there any way to get it not to shift up but to shift down instead?


None

jrbriones

Reply To Post Reply & Quote

Posted at: 12/19/08 01:29 PM

jrbriones NEUTRAL LEVEL 01

Sign-Up: 12/19/08

Posts: 1

At 5/15/08 01:45 AM, oreidoouro wrote: is there any way to get it not to shift up but to shift down instead?

you could just add the new movies on 1


None

XBigTK13X

Reply To Post Reply & Quote

Posted at: 2/21/09 05:23 PM

XBigTK13X LIGHT LEVEL 28

Sign-Up: 08/04/05

Posts: 370

I may add this to the AS3:Main thread if it were formatted properly -___-


None

MrCrinkle

Reply To Post Reply & Quote

Posted at: 3/11/09 08:47 PM

MrCrinkle EVIL LEVEL 10

Sign-Up: 01/26/04

Posts: 340

Is there a way to have something always on the top? I tried putting a really high number in AddChildAt() but it says the index is out of bounds.

If you are reading this then you must be really bored.

BBS Signature

None

P4INKiller

Reply To Post Reply & Quote

Posted at: 4/18/09 01:49 AM

P4INKiller DARK LEVEL 05

Sign-Up: 06/22/06

Posts: 58

At 3/11/09 08:47 PM, MrCrinkle wrote: Is there a way to have something always on the top? I tried putting a really high number in AddChildAt() but it says the index is out of bounds.

That's because you can't have empty slots between depths, the highest depth is always

numChildren - 1

Misunderstood

KannushiLink

Reply To Post Reply & Quote

Posted at: 5/21/09 11:03 AM

KannushiLink LIGHT LEVEL 32

Sign-Up: 08/09/06

Posts: 11

At 5/14/07 06:49 PM, Kinsman wrote: I'd like to add that the display can be an entire tree, not just a simple list - you can manage depths more easily with a technique like this.

// Set up two empty movie clips.

HUDLayer = new MovieClip();
GameLayer = new MovieClip();

// Add them to your stage, or whatever you're using as the main movie clip, so that the HUD's layer is on top of the game's layer.

addChild(GameLayer);
addChild(HUDLayer);

// Now, add some of your custom objects to the layer of choice. All objects in the HUD layer will be on top of all objects in the game layer.

HUDLayer.addChild(new ScoreDisplay());
HUDLayer.addChild(new LivesDisplay());

GameLayer.addChild(new PlayerShip());

I have a problem about this code :

When I draw a background in the FLA file, and use the codes like the above one to add the new MovieClips, the new MovieClips always go behind the backgrounds.

Is there anyway to fix it?


All times are Eastern Standard Time (GMT -5) | Current Time: 07:44 AM

<< Back

This topic is 1 page long.

<< < > >>
You need a Grounds Gold Account to post on the NG BBS! If you don't have one, click here to sign up now! It's fast, free, and easy — and opens up tons of great NG features!