#initclip Pragma | Flash 6 |
starts a movie clip initialization code block |
A nonnegative integer specifying the execution order of this #initclip block relative to all other #initclip blocks in the movie. Those with lower order numbers are executed before those with higher ones. Multiple #initclip blocks can share a single order position.
The #initclip pragma starts a special block of code that allows you to perform initialization for a movie clip symbol before any instances of it are created. As explained in Chapter 14, #initclip typically is used to create so-called components, which are subclasses of the MovieClip class that have been made self-contained for easy use by nonprogrammers. Therefore, the #initclip code block typically is used to register a movie clip symbol with an ActionScript class (i.e., to create a subclass of the MovieClip class, as shown in Chapter 14). An #initclip block can appear only on frame 1 of a movie clip symbol (it causes a compile-time error elsewhere). It is executed only once per movie, according to the export settings for the symbol (set under Options Linkage in the Library panel):
If the symbol is not exported, the #initclip block is executed immediately before the frame where the first instance of the symbol appears.
If the symbol is exported for ActionScript and "Export in first frame" is not selected, the #initclip block, as in the previous case, is executed before the frame where the first instance of the symbol appears.
If the symbol is exported for ActionScript and "Export in first frame" is selected, the #initclip block is executed before the first frame of the movie.
When the #initclip code block is executed, instances of the associated movie clip symbol (even those placed at authoring time), haven't yet been created, so the code executes in the context of the main timeline (_root). Hence, #initclip code has no access to any instance of the symbol in which it is defined. This behavior is intentional; #initclip is used to initialize the whole symbol, not a specific instance, so it must run before any instances are created.
In its most basic form, an #initclip block looks like this:
// CODE ON FRAME 1 OF A MOVIE CLIP SYMBOL #initclip // ...code to link the movie clip symbol to an ActionScript class #endinitclip
The #endinitclip pragma closes the #initclip block (if #endinitclip is omitted, Flash generates a compile-time error). The following code shows a more complete #initclip block placed in a movie clip symbol named ballSymbol. The code creates a custom MovieClip subclass, Ball, and then it uses Object.registerClass( ) to link the ballSymbol (in the movie's Library) to the ActionScript Ball class. Although the #initclip block executes only once, it typically is used to define a constructor that will execute every time an instance of the symbol is created. See Chapter 14 for details on movie clip subclasses.
// CODE ON FRAME 1 OF THE MOVIE CLIP SYMBOL ballSymbol #initclip // Create the custom ActionScript class, Ball. // The constructor is defined when #initclip executes. The constructor runs // whenever a ballSymbol instance is placed on stage (dynamically or manually), // with the keyword this pointing to that instance. function Ball () { // Note that this.color is provided via attachMovie()'s initObj. // See MovieClip.attachMovie() for details. this.setRGB(this.color); } // Set the Ball superclass to MovieClip. Ball.prototype = new MovieClip(); // Associate the Ball class with the library symbol named ballSymbol. Object.registerClass("ballSymbol", Ball); #endinitclip
When an instance of ballSymbol is placed on stage (manually or via ActionScript), the Ball constructor runs with this pointing to the instance. The instance inherits the properties and methods of both Ball and MovieClip. For example:
// Invoke the Ball constructor, which sets the redBall color. Note that // the color property is assigned the value 0xFF0000 by the attachMovie() // method's initObj parameter. this.attachMovie("ballSymbol", "redBall", 1, { color: 0xFF0000 }); // Invoke a MovieClip method on the new instance. redBall.play();
Interestingly, all the code in our #initclip example could have been placed on the main timeline. Creating a custom MovieClip subclass and linking it to a movie clip symbol is not unique to #initclip code. However, by placing the code directly in the movie clip symbol, we create a portable package that can easily be moved from one .fla file to another. To use our MovieClip subclass, a developer simply drags ballSymbol from our Library to hers and creates instances as usual. In fact, to make the movie clip even easier for nonprogrammers to use, we can define component parameters for it, allowing instances to be customized via the Properties inspector. For more information on component parameters, see Chapter 16 and Macromedia's component-building article at:
Returning to our example, we saw earlier that #initclip code executes in the context of the main timeline. Hence, the constructor function Ball is actually created on the main timeline and will appear as _root.Ball. If we know we will not create any subclasses of Ball, we can even delete the constructor from the main timeline by adding this code as the last line of our #initclip block:
delete Ball;
|
To guarantee that a superclass, such as our Ball class, is created before its subclasses, we use the order parameter of the #initclip pragma, which assigns the code block an execution priority level. Multiple #initclip blocks can share the same order level, but those with lower numbers are always executed before those with higher ones. Blocks without a specified order are executed before all numbered blocks. For example, to create a BasketBall subclass of Ball, we use:
// CODE ON FRAME 1 OF THE MOVIE CLIP SYMBOL ballSymbol // Note the order parameter! #initclip 1 // Create the custom ActionScript class function Ball () { this.setRGB(this.color); } // Set the Ball superclass to MovieClip Ball.prototype = new MovieClip(); // Associate the Ball class with the library symbol named ballSymbol Object.registerClass("ballSymbol", Ball); #endinitclip // CODE ON FRAME 1 OF THE MOVIE CLIP SYMBOL basketballSymbol // Note the order parameter! #initclip 2 // Create the custom ActionScript class function BasketBall () { // Invoke the superclass constructor super(); } // Set BasketBall's superclass to Ball BasketBall.prototype = new Ball(); // Associate the BasketBall class with the Library symbol named basketballSymbol Object.registerClass("basketballSymbol", BasketBall); #endinitclip
|
For example, to create a fully qualified reference, we must use this._x to refer to the current movie clip's _x property; if we use an implicit reference to _x, as shown next, the property referenced is _root._x!
Ball.prototype.onEnterFrame = function () { // WRONG! Moves _root, NOT the ball! _x++; // RIGHT. Moves the ball. this._x++; }
Duplicate class names inside separate #initclip blocks do not conflict. For example, if a class constructor named Vehicle is created inside two different #initclip blocks, each movie clip will be associated with its own version of the function, but _root.Vehicle will point to the last one created. This prevents multiple components from breaking due to name conflicts. However, as a matter of good form, using identical class names in a single movie is not recommended. It's normally good form to store each #initclip class on the _global object under a unique namespace, such as _global.org.moock, as described in Chapter 12 and shown throughout Chapter 14.
Code in an #initclip block is not limited to linking a class to a movie clip symbol, although that is its most common use. There's nothing stopping #initclip from performing some other task the first time a particular symbol is used in a movie. The #initclip directive can define an arbitrary block of code that executes before the symbol containing the #initclip block is used for the first time (or when the movie starts, if the symbol is exported in the first frame of the movie):
For example, a movie clip exported for ActionScript in the first frame can be a convenient way to package a global library. The following code creates a Timer class that is available throughout a movie. The movie clip symbol is simply a container for the code; an instance of the symbol is never created.
// CODE ON FIRST FRAME OF AN EXPORTED MOVIE CLIP #initclip _global.Timer = function () { // ...Timer class code goes here... }; #endinitclip // CODE ON ANY TIMELINE IN THE MOVIE gameclock = new Timer();
For much more information on building movie clip subclasses, see Chapter 14.
#endinitclip, MovieClip.attachMovie( ), MovieClip.duplicateMovieClip( ), Object.registerClass( ); Chapter 14