Web DevCenter
oreilly.comSafari Books Online.Conferences.
MySQL Conference and Expo April 14-17, 2008, Santa Clara, CA

Sponsored Developer Resources

Web Columns
Adobe GoLive
Essential JavaScript
Megnut

Web Topics
All Articles
Browsers
ColdFusion
CSS
Database
Flash
Graphics
HTML/XHTML/DHTML
Scripting Languages
Tools
Weblogs

Atom 1.0 Feed RSS 1.0 Feed RSS 2.0 Feed

Learning Lab






An Introduction to OOP in Flash and ActionScript, Part 2
Pages: 1, 2, 3

Extending MovieClip

The MovieClip class happens to be one of the key classes in Flash. Even the simplest of Flash applications utilize movie clips. Creating classes that extend MovieClip can be a very powerful and useful resource. The reason that we're discussing MovieClip subclasses apart from the previous discussion of subclasses in general is that extending MovieClip is somewhat specialized.



In order to create a MovieClip subclass you need to create a MovieClip symbol in the library with which to associate the class. You need to set the symbol to export for ActionScript. And you need to associate the class with the symbol's linkage identifier. Let's take a look at how this works.

The first step in creating a MovieClip subclass is to create a new MovieClip symbol. The symbol may or may not contain artwork and/or nested movie clips, buttons, and text fields, depending on its functionality. Therefore, this step can be as simple as pressing F9, typing in a name, and clicking OK. Because MovieClip instances have a graphical representation, subclass instances should have graphical representation as well. That is why when you create a MovieClip subclass you need to have a symbol with which to associate it.

Once you have created the symbol you should next set it to export for ActionScript and assign it a linkage identifier. You can accomplish this by right-clicking/command-clicking on the symbol in the library and choosing the Linkage menu item. Then, in the Linkage Properties dialog you can click the Export for ActionScript checkbox and then type in a linkage identifier. As a best practice, give the symbol a linkage identifier in the following form: SymbolNameSymbol. For example, if the symbol is named Car, then give it a linkage identifier of CarSymbol.

Typically, for the sake of organization, we define MovieClip subclasses within the symbol with which they are associated. Therefore, you can define the class on the first frame of the symbol's timeline. When you define a class inside a symbol, however, you can run into a problem: Because of the loading order within Flash a class defined within a symbol may not get loaded by the time you try to do something with it. Therefore, you need to tell Flash to load the class first, before anything else in the movie. You can do this with the #initclip and #endinitclip directives. These directives should be placed around all the class definition within the symbol. The #initclip directive should be placed at the beginning, and the #endinitclip should be placed at the end. Just like the #include directive, the #initclip and #endinitclip directives should not be followed by a semicolon.

The class itself is defined much like any other class. And in order to extend the MovieClip class you set the class's prototype to a new MovieClip instance using the MovieClip constructor. This is the one time in which the MovieClip constructor is used in ActionScript.

There is, then, one more step. You still need to tell Flash to associate the class with the symbol. In order to do this you can use the Object.registerClass() method. The method takes two parameters -- a string specifying the name of the linkage identifier for the symbol and a reference to the class. This association established by Object.registerClass() causes Flash to automatically call the constructor of the class whenever a new instance of the symbol is created either during authoring time or during runtime. For this reason, it should be noted, you should not define the constructor to expect any parameters. Instead, if you need to initialize the instances with some values, you should create a method that handles that.

So now that you've had a chance to read the theory, let's see it in practice. Let's create a new MovieClip subclass named CarClass. Follow along with these steps:

  1. Open a new Flash document.
  2. Create a new MovieClip symbol named Car.
  3. Set the symbol to export for ActionScript, and give it a linkage identifier of CarSymbol.
  4. Within the symbol draw a car that faces to the right. If you find yourself artistically challenged, a rectangle with two circles at the bottom will suffice.
  5. Add a new layer to the symbol's timeline. Name the new layer Actions.
  6. On the first frame of the Actions layer add the following code:
    #initclip
    
    function CarClass(){}
    
    CarClass.prototype = new MovieClip();
    
    CarClass.prototype.interval;
    
    CarClass.prototype.drive = function() {
      this.interval = setInterval(this, "moveCar", 10);
    };
    
    CarClass.prototype.moveCar = function() {
      this._x++;
      var bounds = this.getBounds();
      if(this._x + bounds.xMin > 550) {
        this._x = -bounds.xMax;
      }
      updateAfterEvent();
    };
    
    CarClass.prototype.stop = function() {
      clearInterval(this.interval);
    };
    
    Object.registerClass("CarSymbol", CarClass);
    
    #endinitclip
  7. Return to the main timeline.
  8. Rename the default layer to Car.
  9. Drag an instance of the Car symbol from the library to the stage. Name the new instance theCar_mc.
  10. Create a new layer named Actions.
  11. On the first frame of the Actions layer add the following code:
    oListener = new Object();
    oListener.car = theCar_mc;
    oListener.onMouseDown = function() {
      this.car.drive();
    };
    oListener.onMouseUp = function() {
      this.car.stop();
    };
    Mouse.addListener(oListener);
  12. Test the movie.

When you press the mouse the car should move to the right. When you release the mouse, the car will stop. Let's review the code briefly:

First, of course, we enclose the class code in #initclip and #endinitclip directives. Then, we define the CarClass constructor.

#initclip

function CarClass(){}

Because we want CarClass to be a subclass of MovieClip, we assign a new MovieClip instance to the prototype for the class.

CarClass.prototype = new MovieClip();

For clarity we declare the interval property for the prototype. This step is not entirely necessary, but it can be helpful for later determining all the properties of a class.

CarClass.prototype.interval;

The drive() method sets a new interval on which the moveCar() method is called.

CarClass.prototype.drive = function() {
  this.interval = setInterval(this, "moveCar", 10);
};

Note: If you are not familiar with the setInterval() action, you can read more at www.person13.com/ascb/excerpts/setInterval.html.

The moveCar() method increments the object's _x property. Notice that instances of the class only have an _x property because they inherit it from the superclass, MovieClip. Then, we also add a little bit of code that checks to see if the car has gone off the stage. If so, we set it back to the right side of the stage. The updateAfterEvent() action makes sure the stage view refreshes often enough so that the animation is smooth.

CarClass.prototype.moveCar = function() {
  this._x++;
  var bounds = this.getBounds();
  if(this._x + bounds.xMin > 550) {
    this._x = -bounds.xMax;
  }
  updateAfterEvent();
};

The stop() method simply clears the interval so that the moveCar() method is no longer called.

CarClass.prototype.stop = function() {
  clearInterval(this.interval);
};

Then, the Object.registerClass() method tells Flash to associate the class with the symbol with the linkage identifier of CarSymbol.

Object.registerClass("CarSymbol", CarClass);

And then, on the main timeline there is a little bit of code as well. We define a new listener object named oListener. Mouse listener objects can listen for several types of events, including events handled by onMouseDown() and onMouseUp(). Therefore, we define these methods such that when the mouse is pressed the Car instance's drive() method is called, and when the mouse is released the Car instance's stop() method is called.

oListener = new Object();
oListener.car = theCar_mc;
oListener.onMouseDown = function() {
  this.car.drive();
};
oListener.onMouseUp = function() {
  this.car.stop();
};
Mouse.addListener(oListener);

Note: You can download the completed Car example from www.person13.com/ascb/.

Conclusion

That wraps up Part 2 of this article. We started out by talking about how to create instances of the built-in ActionScript classes, and we eventually talked about advanced topics such as creating your own custom classes and even creating subclasses! We covered a lot of material. For more information on these topics you may want to refer to the ActionScript Cookbook, ActionScript for Flash MX: the Definitive Guide, and Colin Moock's Website at www.moock.org. Also, if you have questions about anything in this article, I welcome you to email me at .

Joey Lott is a founding partner of The Morphic Group. He has written many books on Flex and Flash-related technologies, including Programming Flex 3, ActionScript 3 Cookbook, Adobe AIR in Action, and Advanced ActionScript 3 with Design Patterns.


O'Reilly & Associates recently released ActionScript Cookbook.


Return to the Web DevCenter.