Learning ActionScript 3.0: Chapter 4, The Display List
Pages: 1, 2, 3, 4, 5, 6
Continuing our movie clip example, to add a class name to a symbol, select the movie clip in your library, and then click the Symbol Properties button (it looks like an "i" at the bottom of the library) for access to all the symbol properties. Alternatively, you can focus only on the linkage information by choosing Linkage from the library menu, as seen in Figure 4-5.
In the resulting dialog, seen in 4-6, click to enable the Export for ActionScript option, and add a name to the Class field. When you start working with classes, you will follow a few simple rules and conventions, one of which is to capitalize the first letter of your class name. This is a bit different from naming a variable, where you might choose to use a lowercase first letter, so it's a good idea to get into this practice now. In the addChild.fla source file, we've used the class name Unicycle.
You will also likely notice that Flash adds the MovieClip class (in this case) to the Base class field for you. This makes it possible to automatically access the properties, methods, and events available to the MovieClip class. For example, you can automatically manipulate the x and y coordinates of your new custom movie clip.
Now that you've given your movie clip a class name, you can create an instance of that custom movie clip class the same way you created an instance of the generic movie clip class. Instead of using MovieClip(), however, you will use Unicycle() to create the movie clip. The same call of the addChild() method is used to add the newly created movie clip to the display list, as seen in the following code. A finished example of this code also exists in the accompanying source file addChild2.fla.
var cycle:MovieClip = new Unicycle(); addChild(cycle);
The addChild() method adds the display object to the end of the display list, which places the object at the top-most z index. This makes it very easy to place items on top of all other items. It's also useful to be able to add a child at a specific position in the display list. For example, you may wish to insert an item into the middle of a vertical stack of display objects.
This example, found in the addChildAt.fla source file, adds a movie clip with the class name Ball to the start of the display list with every mouse click. The ultimate effect is that a new ball is added below the previous balls, and positioned down and to the right 10 pixels, every time the mouse is clicked.
1 var inc:uint = 0;
2
3 stage.addEventListener(MouseEvent.CLICK, onClick, false, 0, true);
4
5 function onClick(evt:MouseEvent):void{
6 var ball:MovieClip = new Ball();
7 ball.x = ball.y = 100 + inc * 10;
8 addChildAt(ball,0);
9 inc++;
10 }
Line 1 initializes a variable that will be incremented with each ball added. Line 3 adds an event listener to the stage, listening for a mouse click, so that any mouse click will trigger the listener's function. The function in lines 5 through 10 performs four basic tasks. In line 6, a new Ball movie clip is created.
Line 7 manipulates the x and y coordinates in a single instruction, setting x equal to y, which is equal to the value of an expression. This is handy when both x and y values are the same. In this case, the expression sets the new ball to x and y of 100 and adds a 10-pixel offset for each ball added. For example, when the first ball is added, inc is 0 so the additional pixel offset is 0*10 or 0. Then inc is incremented at the end of the function, in line 9. The next mouse click that calls the function will update the offset to 1*10 or 10 pixels for the second ball, 2*10 or 20 pixels offset for the third ball, and so on. Most importantly, line 8 adds the ball to the display list, but always at position 0, making sure the newest ball is always on the bottom.
Note: It is possible to manipulate display objects—such as setting properties or invoking methods—both before and after the object has been added to the display list. By doing this, you can create a display object, initialize its properties to your liking, but reserve adding it to the display list until it is needed. See the sidebar "Display Objects and References to Stage and Root" for a notable exception to this rule.
This excerpt is from Learning ActionScript 3.0. Learning ActionScript 3.0 gives you a solid foundation in the Flash language and demonstrates how you can use it for practical, everyday projects. The book does more than give you a handful of sample scripts, defining how ActionScript and Flash work. It gives you a clear look into essential topics such as logic, event handling, displaying content, migrating legacy projects to ActionScript 3.0, classes, and much more. Written for those new to the language, this book doesn't rely exclusively on prior knowledge of object-oriented programming (OOP). Instead, it helps you expand your skillset by first focusing on clear, concise examples in the timeline, evolving into OOP examples over time-allowing you to choose the programming approach with which you are most comfortable.
It can be advantageous to manipulate display objects prior to adding them to the display list. For example, you may wish to change properties of an object over time, but prior to that object being visible or being capable of responding to events. If you added the object to the display list immediately, these changes may be seen or experienced by the end user.
Some display object properties or methods, however, may not be valid when the object is not part of the display list. Good examples of this scenario include the root and stage instances of any display object.
Once a display object is added to the display list, its stage and root properties are valid. However, if the object is not part of the display list, its stage property will always return null, and the root property will be valid only if the display object is already a child of another container in a loaded SWF.
Try the following example. You will see that, until the created movie clip is added to the display list, both its stage and root properties are null.
//create display object
var mc:MovieClip= new MovieClip();
// reference to stage and root return null
trace(mc.stage);
trace(mc.root);
//add the object to the display list
addChild(mc);
//references to stage and root return Stage and
Main Timeline objects respectively
trace(mc.stage);
trace(mc.root);
Invalid stage and root properties can be a common problem if you don't plan ahead. For example, the following code tries to set the location of a movie clip to the center of the stage prior to adding the object to the display list. However, this will fail because querying the stageWidth property of the object's stage reference will not work until after adding the object to the display list.
var mc:MovieClip = new MovieClip(); mc.x = mc.stage.stageWidth/2; addChild(mc);
This problem can be corrected by transposing the last two lines of the script. It is also possible to work with the stage directly, as its own entry in the display list, as seen in the following snippet:
var mc:MovieClip = new MovieClip(); mc.x = stage.stageWidth/2; addChild(mc);
However, this is not always possible when using root, because the root of a display object is relative to the object itself. Keep this in mind if you get unexpected results, and check to make sure you are referencing these instance variables only after adding the object to the display list.
It's equally important to know how to remove objects from the display list. The process for removing objects is nearly identical to the process for adding objects to the display list. To remove a specific display object from the display list, you can use the removeChild() method:
removeChild(ball);
Remove a display object at a specific level using removeChildAt():
removeChildAt(0);
The following example is the reverse of the addChildAt() script discussed in the prior section. It starts by using a for loop to add 20 balls to the stage, positioning them with the same technique used in the prior script. (For more information on for loops, please review .) It then uses the event listener to remove the children with each click.
1 for (var inc:uint = 0; inc < 20; inc++) {
2 var ball:MovieClip = new Ball();
3 ball.x = ball.y = 100 + inc * 10;
4 addChild(ball);
5 }
6
7 stage.addEventListener(MouseEvent.CLICK, onClick,false, 0, true);
8
9 function onClick(evt:MouseEvent):void{
10 removeChildAt(0);
11 }
The previous script works if something's in the display list. If after removing the last ball, you click the stage again, you're warned "the supplied index is out of bounds." That's because you're trying to remove a child from position 0 of the display list, when there's nothing in the display list at all.