For now, our Ball constructor (from Example 14-1) is defined on the main timeline of our .fla file. Later, we'll see how to move the constructor to our ballSymbol Library symbol. The Ball constructor looks very much like the constructor functions we saw in Chapter 12, with the added feature that it is defined in a global namespace corresponding to the domain name, moock.org (your classes should be defined in your domain's namespace, as in com.yoursite.YourClass):
/* * Ball Class Constructor. */ org.moock.Ball = function ( ) { // Create Instance properties. // ... // Initialize instance. // ... };
However, you'll notice that our class constructor does not define any parameters! Remember that we're creating a MovieClip subclass, and movie clip instances are not created with the standard new Object( ) instantiation, which facilitates parameters. Instead, movie clip instances are created with the functions attachMovie( ) or duplicateMovieClip( ), which generate the instance and invoke its class constructor (if one is defined). Hence, to supply arguments to our Ball constructor function, we have to pass them through either attachMovie( ) or duplicateMovieClip( ). But we can't pass the arguments directly, as we would with the syntax: new Object(arg1,...argn). Instead, we must use a so-called initObject�an object whose properties are copied to the new instance just before the constructor function runs.
For example, the following code attaches an instance of the movie clip symbol exported as "boxSymbol":
var initObj = new Object( ); initObj.description = "A four-sided figure"; this.attachMovie("boxSymbol", "box_mc", 2, initObj);
The code names the new instance "box_mc", places it on depth 2, and passes it an initObject with a single property, description. After the code runs, the box_mc instance will have a description property set to the value "A four-sided figure".
In place of true parameters, MovieClip subclass constructors are expected to use the properties set by the attachMovie( ) or duplicateMovieClip( ) initObject. For example, our Ball constructor (shown next) relies on the initObject's params property�which itself is an object�to pass the parameters x, y, velocity, radius, and ballColor to the constructor:
org.moock.Ball = function ( ) { // Create instance properties this.velocity = this.params.velocity; // Initialize instance this.setPosition(this.params.x, this.params.y); this.setColor(this.params.ballColor); this.setSize(this.params.radius); this.onEnterFrame = this.move; // Remove constructor params object from the instance delete this.params; }
When attaching a new instance, we create our initObject like this:
// Create an object whose properties will be used // as the Ball constructor's parameters. var ballParams = new Object( ); ballParams.radius = 10; ballParams.ballColor = 0xFF0000; ballParams.x = 250; ballParams.y = 250; ballParams.velocity = {x:12, y:4}; // Assign the ballParams object to the single initObj.params property. var initObj = new Object( ); initObj.params = ballParams; // Now pass initObj to the instance via attachMovie( ). The params // property is copied to the new instance, with all the constructor // parameters defined by ballParams. this.attachMovie("ballSymbol", "redBall", 1, initObj);
In Example 14-1, these instance-creation statements occur within the main( ) function, so both ballParams and initObj variables are local, and they are deleted automatically when main( ) finishes executing. Otherwise, we would have had to delete ballParams and initObj explicitly, or supply our initObject as an object literal that would not persist after being passed to attachMovie( ).
You might wonder why we bothered with a params property. That is, why not just define the radius, velocity, ballColor, _x, and _y properties directly on the initObject and use them directly in our Ball constructor, as follows?
// Constructor code org.moock.Ball = function ( ) { // Initialize instance. this.setColor(this.ballColor); this.setSize(this.radius); this.onEnterFrame = this.move; }; // Attach movie call var initObj = new Object( ); initObj.radius = 10; initObj.velocity = {x:44, y:2}; initObj.ballColor = 0xFF0000; initObj._x = 30; initObj._y = 12; this.attachMovie("ballSymbol", "redBall", 1, initObj);
While setting object properties directly on the initObj works, it poses two problems:
Code is not properly centralized: the attachMovie( ) function takes on the responsibility of creating instance properties, which should be the role of the constructor function.
Constructor parameters (which should be temporary) are left as permanent properties of the new instance. The property ballColor, for example, is no longer needed after construction, yet it remains defined for as long as the instance exists.
To centralize our code and ensure that our instance is not unnecessarily cluttered with constructor-parameter properties, we define all our parameters on a single params property of the initObject. When the constructor finishes executing, it then deletes the params property:
// Remove constructor params object from the instance. delete this.params;