23 November 2010
Intermediate
When ActionScript code is entered into the Actions panel it is linked to the currently selected frame of the FLA file. A SWF file, even one of great code complexity, can be compiled from code that exists only by framescripts, or code on frames of the timeline. However, using framescript code has several drawbacks, including:
Writing ActionScript in external files avoids these drawbacks. The external files can be edited even by those without the authoring tool, so both designers and developers can work in tandem. The formalized structure also encourages better code and makes reuse easier both for future Flash and Flex projects.
To link a FLA file to external ActionScript, specify a document class. To do this, deselect any stage items you may have selected and open the Properties panel. This panel contains settings related to your document, including background color and frame rate. It also contains a Document class field. Set this field to the name of your external file without the AS extension. This file must contain a public class whose name matches the name of the file before the AS extension.
For example, create a new FLA and save it as TestFile.fla. Create a new AS file, either within Flash Professional or your preferred text editor, and save it as MyClass.as in the same directory as your FLA file. Enter this code into MyClass.as:
package
{
import flash.display.Sprite;
public class MyClass extends Sprite
{
public function MyClass() {
trace("Hello World");
}
}
}
In the Properties panel of TestFile.fla, set the Document class field to "MyClass" and save. Testing the movie causes "Hello World" to trace to the output panel.
Note: The import statement in MyClass.as, as with any imports of the flash.* namespace, is unnecessary for code written on the timeline because Flash Professional automatically imports these packages before compiling. Since this does not occur for external files, the import statement is essential for successful compilation of any external ActionScript file that uses a class from the flash.* namespace.
By default, instances of movie clip symbols in a Flash document's library cannot be dynamically created (that is, created from ActionScript). This is because each symbol that is exported for use in ActionScript adds to the size of your SWF file. For this reason, in order to make a symbol available in ActionScript, you must specify that the symbol be exported for ActionScript.
To export a symbol for ActionScript:
By default, the Class field is populated with the symbol name, with spaces removed (for example, a symbol named "Tree House" would become "TreeHouse"). To specify that the symbol use a custom class for its behavior, enter the full name of the class including its package in this field. If you want to be able to create instances of the symbol in ActionScript, but don't need to add any additional behavior, you can leave the class name as-is.
After changing the linkage settings, Flash will attempt to find an external ActionScript file with a definition for the specified class in the Class field. If it does not find one, it will show a warning. This warning can be ignored if you do not need additional behavior beyond the functionality of the MovieClip class, since one will be automatically generated for it. An automatically generated class looks analogous to the following:
package
{
import flash.display.MovieClip;
public class ExampleMovieClip extends MovieClip
{
public function ExampleMovieClip() {
}
}
}
The value of the Base Class defaults to flash.display.MovieClip. Use this default unless you are using an automatically generated class that uses the functionality of an external class. Base Class is not synonomous with extension; if you are specifying a custom class that itself extends another class, it is not necessary to specify this superclass as the Base Class. In this situation, the default of flash.display.MovieClip is sufficient. If, however, you wanted two symbols, RedFish and BlueFish, to function identically but have different skins, you could use the authoring tool to create different appearances, then set their Base Class to Fish and use a Fish class in an external Fish.as file to provide the functionality for both fish.
When making a custom class, create an external file with the structure of an automatically generated class, then add the appropriate properties and methods to the class. For example, suppose you have a movie clip symbol containing a circle of 50 pixels width and 50 pixels height, and the symbol is specified to be exported for ActionScript with a class named Circle. The following code, when placed in a Circle.as file that is saved in the same directory as the FLA file, extends the MovieClip class and provides the symbol with the additional methods getArea() and getCircumference():
package
{
import flash.display.MovieClip;
public class Circle extends MovieClip
{
public function Circle()
{
}
public function getArea():Number
{
// The formula is Pi times the radius squared.
return Math.PI * Math.pow((width / 2), 2);
}
public function getCircumference():Number
{
// The formula is Pi times the diameter.
return Math.PI * width;
}
}
}
The following code, placed on a keyframe on Frame 1 of the Flash document, creates an instance of the symbol and displays it on the screen:
var c:Circle = new Circle();
addChild(c);
trace(c.width);
trace(c.height);
trace(c.getArea());
trace(c.getCircumference());
This code demonstrates ActionScript-based instantiation as an alternative to dragging individual assets onto the Stage. It creates a circle that has all of the properties of a movie clip and also has the custom methods defined in the Circle class.
Timeline tweens can grow difficult to create and manage as they accumulate, especially if they begin and start on different frames. Using external classes can streamline this process and make modifications easier.
For example, suppose you want to make an animation of snowfall. One workflow possibility is to use timeline tweens and framescripts. In this method, you could make a snowflake symbol and provide a series of tweens of the symbol floating downward. Then place several instances across the top of the stage. When the movie is run, you'll have several snowflakes floating downward.
At this point, the snowfall would not look especially realistic since each snowflake's appearance and animation would be identical. You could add variety by selecting each snowflake and modifying its alpha property. You could also duplicate the snowflake symbol, making new snowflakes that travel slower or over wider paths. But there are drawbacks to this process. If, partway through creating your final snowflake, you realize it would be useful to set the alpha property to zero in the final keyframe so as to convey a fading snowflake, you would need to alter each snowflake movie clip. While adding variety in this way is possible using the authoring tool, its benefit is dependent upon time and manual precision, and can quickly grow time consuming and difficult to modify later.
Leveraging ActionScript is an alternative to this process. Instead of creating several snowflake movie clips and maintaining distinct tweens within each, create one that exports for ActionScript and specify a custom class named Snowflake in its symbol properties. Then, create an ActionScript file that is modeled after an automatically generated class. Finally, add properties and methods that define the behavior of the snowflake. Programmatic animation can replace many tweens made in the authoring tool.
Here is an example of a custom Snowflake class which uses the Event.ENTER_FRAME event to update the position of the snowflake (save this in a file named Snowflake.as):
package {
import flash.display.Shape;
import flash.events.Event;
import flash.filters.BlurFilter;
public class Snowflake extends Shape {
private var stageWidth:int = 550;
private var stageHeight:int = 450;
private var highestDropSpeed:uint = 16;
private var dropSpeed:int = Math.round(Math.random() * Math.random() * highestDropSpeed);
private var incrementer:int = Math.round(Math.random() * 100);
private var shades:Array = [ 0xFFFFFF, 0xCCCCCC, 0x999999, 0x666666 ];
private var windSpeed:int = 2;
public function Snowflake() {
graphics.beginFill(shades[ Math.ceil(Math.random() * shades.length) ]);
graphics.drawCircle(0,0,4);
graphics.endFill();
filters = [ new BlurFilter(1,dropSpeed,1) ];
addEventListener(Event.ENTER_FRAME,update);
reset();
}
private function reset():void {
y = Math.random() * stageHeight * -1;
x = Math.random() * stageWidth - (windSpeed*100);
scaleX = scaleY = 0.25 + (Math.random() * Math.random() * 0.75);
}
private function update(e:Event):void {
y += dropSpeed;
x += windSpeed + Math.sin(incrementer/10) * (1/(dropSpeed/3));
if (y > stageHeight) {
reset();
}
incrementer++;
}
}
}
To create a snowfall animation, add the following code to a FLA file with a black background, and save the FLA file to the same directory as the Snowflake.as class file:
for(var i:uint; i<800; i++){
var snowflake:Snowflake = new Snowflake();
addChild(snowflake)
}
Result
To get the source files for this example, download Snowfall.zip at the top of this page.
A total of 800 snowflakes are created, each with distinct characteristics of size, speed, and color, and modifications to the external class can create significant effects on the visual display. The end result is a more realistic snowfall than could be created by hand in the authoring tool.
Animation created using the Timeline can migrate to ActionScript using Motion XML Elements, preserving any easing and filters that may be applied. To do this, select a series of frames that encompass a tween and select Export Motion XML from the Commands menu in Flash. A basic exported XML file looks something like this:
<Motion duration="10" xmlns="fl.motion.*" xmlns:geom="flash.geom.*" xmlns:filters="flash.filters.*">
<source>
<Source frameRate="31" x="0" y="0" scaleX="1" scaleY="1" rotation="0" elementType="movie clip" symbolName="Symbol 1">
<dimensions>
<geom:Rectangle left="0" top="0" width="10" height="10"/>
</dimensions>
<transformationPoint>
<geom:Point x="0" y="0"/>
</transformationPoint>
</Source>
</source>
<Keyframe index="0">
<tweens>
<SimpleEase ease="0"/>
</tweens>
</Keyframe>
<Keyframe index="9" x="10">
<tweens>
<SimpleEase ease="0"/>
</tweens>
</Keyframe>
</Motion>
The XML can either be imported back into the authoring environment by selecting an object on stage and running the Import Motion XML command, or by using the Animator class to apply the Motion XML Element to a display object by code.
The following example uses the Animator class to assign a Motion XML Element to a display object on the stage named box:
import fl.motion.Animator;
var motionXML:XML =
<Motion duration="10" xmlns="fl.motion.*" xmlns:geom="flash.geom.*" xmlns:filters="flash.filters.*">
<source>
<Source frameRate="31" x="0" y="0" scaleX="1" scaleY="1" rotation="0" elementType="movie clip" symbolName="Symbol 1">
<dimensions>
<geom:Rectangle left="0" top="0" width="10" height="10"/>
</dimensions>
<transformationPoint>
<geom:Point x="0" y="0"/>
</transformationPoint>
</Source>
</source>
<Keyframe index="0">
<tweens>
<SimpleEase ease="0"/>
</tweens>
</Keyframe>
<Keyframe index="9" x="10">
<tweens>
<SimpleEase ease="0"/>
</tweens>
</Keyframe>
</Motion>
var animator:Animator = new Animator(motionXML,box);
animator.play();
Related Flash Quick Starts