Getting Started with ActionScript 3.0 in Adobe Flash CS3
With Flash CS3 comes support for ActionScript 3.0 - the newest, standards-based programming language for Adobe Flash (SWF) movies and applications. More so than in the past, you may find it difficult to get started with ActionScript 3.0 compared to older versions of ActionScript. The transition from ActionScript 2 from ActionScript 1, for example, could probably be seen as a cakewalk compared to the leap to ActionScript 3.0, especially for someone who is prone to working and coding in the Flash IDE (Integrated Development Environment). This article will help acclimate you to working with ActionScript 3.0 within the Flash CS3 IDE.
Requirements:
- Flash CS3
- A Basic understanding of ActionScript or at least JavaScript
Not using or don't have Flash CS3? Learn to use ActionScript 3 using the Free Flex 2 SDK with the Beginners Guide to Getting Started with ActionScript 3 (Without Learning Flex).
A Brief History of ActionScript
Early syntax of ActionScript 1 with Flash 3 was simple and verbose and functionality was based mainly around frame navigation and basic mouse interaction. This remained consistent until about Flash 5 where ActionScript assumed a form more similar to JavaScript. This provided a great deal more functionality and a "dot-syntax" for variable and method access. ActionScript also became a prototyped language allowing for simple OOP functionality similar to that available in JavaScript. This was enhanced in the following release of Flash, Flash MX (6).
Flash MX 2004 (7) introduced ActionScript 2.0. There were two major improvements that came with ActionScript 2: variable data typing and a new class syntax. The variable data typing that ActionScript 2 supported was strictly for compile-time debugging. What this meant was that any type you associated with a variable was stripped away from the code when you compiled or published your movie and was used to, at that point in time, check against discrepancies within your own code. If no conflict was found during the compilation process, your SWF would be created and the ActionScript inside would run without any understanding of the types you assigned to them in your original code. Though this provided no advantage to the Flash Player during playback, it did provide Flash authors a helpful tool for debugging larger, more complicated applications.
The new class syntax was used to define classes in ActionScript 2 similar to those defined for languages like Java. Though Flash still didn't really support classes beyond its own prototypes (in the end, ActionScript 2 gets compiled to ActionScript 1), this new syntax provided a familiar style that was helpful for people migrating from other languages and provided a more concrete way to organize class definitions within separate AS files and packages.
That brings us to Flash CS3 (9; not much happened with Flash 8) with ActionScript 3.0. Here we have a new ActionScript language that not only received a new version number but also a new virtual machine �C the underlying software within the Flash Player that executes ActionScript during playback. Both ActionScript 1 and ActionScript 2 use AVM1 (ActionScript Virtual Machine 1) as they are essentially the same in terms of needs for playback �C remember ActionScript 2 mostly only added compile-time type checking and a new syntax which essentially became ActionScript 1 when compiled �C whereas ActionScript 3 runs in AVM2, the new virtual machine specifically for ActionScript 3 code. As a result not only can ActionScript 3 movies not directly communicate with ActionScript 1 or ActionScript 2 movies (ActionScript 1 and ActionScript 2 movies can because they use the same virtual machine; AVM1 and AVM2 movies can only communicate through local connection), but you may find that the changes in ActionScript 3 to be much more profound than the jump even from ActionScript 1 to ActionScript 2.
Code examples (of classes similar in functionality) from each version of ActionScript:
ActionScript 1
function Example(){
this.num = 1;
}
Example.prototype.str = "text";
Example.prototype.doubleNum = function(){
this.num *= 2;
}
ActionScript 2
class Example {
public var num:Number;
private var str:String = "text";
public function Example(){
this.num = 1;
}
public function doubleNum():Void {
this.num *= 2;
}
}
Note: When compiled, the above ActionScript 2 class becomes equivalent to ActionScript 1 example.
ActionScript 3
package {
public class Example {
public var num:Number;
protected var str:String = "text";
public function Example(){
this.num = 1;
}
public function doubleNum():void {
this.num *= 2;
}
}
}
How different is ActionScript 3?
ActionScript 3 is different. Very different. So different, in fact, that it requires a completely new virtual machine to run it. But at its core, its still ActionScript and as ActionScript you'll notice that many of the commands and programming concepts that applied to ActionScript 1 and ActionScript 2 still pretty much apply to ActionScript 3. Even with the example above, very little, at least syntactically, has changed. And sometimes the ActionScript 3 equivalent of ActionScript 2 code will look very similar, but not always. And in the end, there are enough changes to make a direct conversion between the two often very difficult.
These changes were necessary, though. ActionScript 3 was built with efficiency and productivity in mind. Not just efficiency in development (and this point can be argued for smaller projects but larger projects do benefit) but also playback performance where code in ActionScript 3 can be played back in the Flash Player up to 10 times (if not more) faster than ActionScript 2 code. Yes, you will find that many of the same menial tasks in ActionScript 1 and ActionScript 2 now seem to take twice as long to code in ActionScript 3, but in the end the extra speed and functionality. The casual coder may look to the sky shaking a fist, cursing, but the advanced programmer will jump with glee in rejoice.
Here are some of the new features in ActionScript 3:
- Runtime exceptions �C errors that are thrown at runtime to help debug your project
- Runtime variable typing �C typing which goes beyond compilation and persists during playback
- Sealed classes �C classes based on a static definition for additional robustness and performance
- Method closures �C methods are now bound to their respective class instance so 'this' in methods will never change
- E4X �C a new, easy to work with implementation of XML
- Regular expressions �C native support for regular expressions
- Namespaces �C support for namespaces not only in XML but in class definitions to set custom access to class members
- int and uint data types �C new data types for Number values allowing ActionScript to use faster integer-based math for certain calculations
- New display list model �C a new, flexible approach to managing display objects to be displayed on the screen
- New event model �C a new, listener-based event model supporting event propagation
Where you write code in Flash CS3
When you write code in a Flash source file (FLA) using ActionScript 3, you're writing code on the timeline and only the timeline. If not writing in the timeline then you're writing code in an external class file (at which point you wouldn't be writing code in the FLA, now would you?). In ActionScript 1 and ActionScript 2, you could write code on the timeline as well as on objects such as buttons or movie clips when adding code to the Actions editor with those objects selected. Code then would be added within on() or onClipEvent() blocks and related to some kind of event like press or enterFrame. This is no longer possible in ActionScript 3. Code can only be written on the timeline and all events, like press and enterFrame now have to be defined there as well.
Figure: ActionScript cannot be assigned to selections
Variables
Variables are words in code that represent or contain different values or data. When you declare variables in ActionScript 3, you need to use the var
keyword.
var myVariableName; // var required
The var
keyword has been available in ActionScript 1 since Flash 5 but only now, in ActionScript 3 is it required. The only exception is when defining a new variable value in a dynamic object instance (one whose variable definitions are not predefined) using an explicit reference to that object.
myDynamicObject.newVar = value; // var not used
In the above example, newVar is a new variable being defined in the myDynamicObject object without the use of var. In fact, var can never be used with complex references, or any reference that requires a dot (.) or bracket access ([]) to reference the variable.
When defining a variable you must only use numbers, letters, dollar signs ($) and underscores (_) and a variable cannot start with a number. Whereas "bits32", "_bits32", and "$bits32" are valid, "32bits" is not valid for a variable name since it starts with a number.
You will also have to be sure not to create naming conflicts with your variable names and any internal variable names already defined in the current scope of your script. For example, when writing code in any timeline, you are writing code that is being defined for a MovieClip instance �C the MovieClip instance that is represented by that timeline. If you try to define a variable with a name that is the same as a predefined MovieClip variable (or function) you will get an error.
// Any timeline script
var name:String = "Joe"; // Error: A conflict exists with inherited definition
Similarly, you should not name variables after global objects or functions like Array, XML, or trace or those definitions will no longer be accessible to you.
Note: Since Flash Player 7, ActionScript is case sensitive, so the variables Name and name are not the same.
New to ActionScript 3 is the restriction that you can only declare a variable with var once in any one scope or timeline in code. In other words, if you declare the variable x at the top of your script and want to use it again at the bottom of your script, you should not use the var keyword for that variable again
var x = value; // ok
…
var x = differentValue; // error; you can only use var once
When defining variables on the timeline in Flash, this also applies to all frames in the same timeline, not just the current frame.
When declaring variables with the var keyword (and only with the var [or const] keyword) you have the option of specifying a variable type. A variable's type describes the kind of value it will be holding. This was a new feature in ActionScript 2 and continues to exist in ActionScript 3. So, for example, if you wanted the variable x to hold a number value, you would specify it as being of the type Number using the following:
var x:Number; // variable x contains number values
In both versions of ActionScript, typing like is optional. ActionScript 3, however, will also retain type information during movie playback, unlike ActionScript 2 which used it strictly for compile-time (during publishing) error checking. This means that you will have to be much more respective of your type decisions, especially since you cannot redefine a variable with var a second time in ActionScript 3 (doing this in ActionScript 2 would let you use different types for one variable).
By not typing a variable at all, you can use any type you want for that variable. However, ActionScript 3 also provides a special "untyped" type that represents just that �C no type. It is represented by an asterisk (*).
var anyValue:*; // variable can have any type
It's always good to specify some type for your variable as it can lead to better error checking and performance. By using the untyped type, you can specifically indicate that the variable can have any value without reading others reading the code to guess.
If you do not supply a variable with a default value, it will be assigned one based on its type. If no type was supplied, it will be given a value of undefined
. The following list details the default values of different data types in ActionScript 3:
var untyped:*; // (or no typing) undefined
var boolean:Boolean; // false
var number:Number; // NaN
var integer:int; // 0
var unsignedInteger:uint; // 0
var string:String; // null
var object:Object; // null
Any other Object type results in default value of null. It should be noted that values of the type object (any kind of object including arrays and objects created from custom classes) have a default value of null, not undefined. In fact objects in ActionScript cannot be undefined. If they have no value, then they are null. Only with untyped variables or attempting to access variables that do not exist will get a value of undefined.
Number types are now unique in that they can no longer be undefined or null. If they have no value, they are seen as NaN ("Not a Number"). NaN is a tricky value, however. You can't really compare NaN with another NaN with the equality operator (==) because they probably won't be the same. If you ever need to check to see if a number is NaN, you should always use isNaN()
.
if (isNaN(myNumber)) // checks to see if Number is defined
The int and uint variables types are new in ActionScript 3. These are special kinds of Numbers that represent 32-bit integers or whole numbers. The int type is a normal integer and uint is an unsigned integer, or a whole number whose value cannot be negative. These kinds of numbers can only have whole number values. They cannot be null, undefined., or even NaN like the Number type on which they are based. Being that they are based on the Number type, however, you'll notice that they're type identities ("int" and "uint") are not capitalized. This indicates that there is no specific object type or class definition associated with that type. Instead, these types essentially share the Number definition with Number types (with the exception of the MIN_VALUE and MAX_VALUE constants).
There is one other type that is also not capitalized. This is the special void type. This was capitalized in ActionScript 2 but is no longer in ActionScript 3 since, like with int and uint, there is no specific definition associated with it. This type has not been seen so far as it only applies to functions.
Functions
Functions define reusable chunks of code, or custom operations in ActionScript. By creating a function you can perform the same operation multiple times without having to write the same code over again for each time you want to use it.
There are two ways to define functions in ActionScript. You can create a named function using the form function [functionName] ([parameters]) { [code] } or you can define an anonymous function using var [functionName] = function ([parameters]) { [code] }. Both essentially create a variable definition (following the same naming conventions used by variables) with a value of Function, though the second method does so a little more explicitly.
// Named function
function doubleNumber(num) {
return num*2;
}
// Same function defined as an anonymous function
var doubleNumber = function(num) {
return num*2;
}
The above example creates a function with the name doubleNumber which accepts a single number value and returns that value multiplied by two. To use the function, you call it using parentheses (()).
var x:Number = 10;
trace(doubleNumber(x)); // traces 20
As with variables, named functions cannot be defined more than once for any one given timeline
When assigning type to functions, define typing information for both the parameter list (the comma separated list of values you can supply the function) as well as the return value, or the value that the function supplies after it's executed. When using an anonymous function definition, the variable the function is being assigned to would also be typed to Function.
// Named function
function doubleNumber(num:Number):Number {
return num*2;
}
// Same function defined as an anonymous function
var doubleNumber:Function = function(num:Number):Number {
return num*2;
}
If a function does not return a value, then its return type should be void. When a function typed as void is executed, or simply fails to return a value with the return statement, its return value becomes undefined.
function returnsNothing():void {
// do nothing
}
trace(returnsNothing()); // traces undefined
The returnsNothing
function above not only returns nothing, but also accepts no values �C it has no parameter list. If you try to pass values into the function when it has no parameter list defined for it in ActionScript 3, you will get an error.
returnsNothing(3); // Error: Incorrect number of arguments
In ActionScript 2, the Void type was used as the parameter list in a function definition to indicate no parameters. In ActionScript 3, you just leave the list empty.
Note: The difference between parameters and arguments is that parameters are the value used to define the function. Arguments are the actual values provided to the function during use. You can see arguments as being parameter values.
With ActionScript 3, you can also now define default values for your functions.
// Here, message parameter is optional
function usesDefault(message:String = "hello"):void {
trace(message);
}
usesDefault("test"); // traces "test"
usesDefault(); // traces "hello"
By using defaults you not only get to specify values for parameters not used by the function caller, but it also lets you define functions with optional parameters, or parameters that aren't required to be used. Those parameters that do not have default values must be provided when the function is called. Because of this, all optional parameters must be defined at the end of a parameter list. You cannot have a required parameter defined after an optional.
// Error: Required parameters are not
// permitted after optional parameters
function usesDefault(message:String = "hello", num:Number):void {
// code
}
// Correct; usesDefault needs at
// least 1 argument, accepts 2 at max
function usesDefault(num:Number, message:String = "hello"):void {
// code
}
What if you wanted to allow a function to be called with any number of arguments? In ActionScript 2, you could do this simply by omitting any parameter list and referencing the arguments using the arguments object in the function. In ActionScript 3, having no parameter list means the function cannot be called with any arguments. Instead, you have to use a new parameter type known as …(rest). This parameter goes at the end of your parameter list (or it can be your entire parameter list) and indicates that any number of arguments can be used when calling the function. The …(rest) parameter is written as …[argumentsArrayName] where argumentsArrayName is the name of the array that will contain the arguments passed.
function passAnything(...statements):void {
trace(statements.length +": "+ statements);
}
passAnything(); // traces 0:
passAnything(1); // traces 1: 1
passAnything("a", true, 0); // traces 3: a,true,0
Note: When using … (rest) parameter, the arguments object is not available to the function call. Instead, the …(rest) parameter is to be used to obtain the arguments passed. Unlike arguments, however, …(rest) does not have the caller property used to reference the current function. In ActionScript 3, neither arguments nor …(rest) have the callee property used to reference the function calling the current function (callee was available in the arguments object in ActionScript 2 but removed in ActionScript 3).
Objects, Properties, Methods, and Classes
Objects are complex values that contain, or can contain, additional values known as properties. The most basic kind of object is an Object object and is created using new Object().
var myObject:Object = new Object();
There are other kinds of objects in ActionScript that behave similarly. Every timeline in Flash, for instance, represents the timeline of a movie clip symbol which in ActionScript is represented by a MovieClip object or instance. The name variable of a timeline or MovieClip is a property of that MovieClip instance.
// Main timeline
trace(name); // traces "root1"
Functions defined in objects are known as methods. Together, properties and methods make up an object's members. Methods unique to MovieClip instances include gotoAndPlay()
and gotoAndStop()
. Primitive values like Boolean (true or false), Number (numeric values), and String (text characters) are not objects in the true sense as they represent basic values and do not act as containers for other values. Flash does, however, associate these primitives with certain object types (Boolean, Number, and String), or classes, which grants them certain object-like functionality. So, for instance, you can extract a certain chunk of text from a String primitive using the String.slice()
method of the String class.
Classes are what define objects. They also act as an object type. The Array class, for instance, defines what properties and methods exist in Array instances (whose type is Array). When you look through the documentation available for Arrays, you're looking at a reference to the Array class.
var arrayInstance:Array = new Array(); // instance of Array class
With Object Oriented Programming (OOP), you are writing custom classes that define custom object instances. With a more traditional, or procedural, approach, you are mainly defining variables and functions that work together but without much emphasis on object usage. In Flash, this means writing code on the timeline. More about just how timelines and ActionScript work together will be covered later.
Since ActionScript 2, some classes in ActionScript were marked as being sealed. More specifically, they weren't marked dynamic (the opposite of sealed). If a class is not dynamic, then it is sealed. When a class is sealed, it means that instances of that class cannot have any additional variables or properties defined for them outside of those specified in the class's definition. The Object and Array classes in ActionScript are dynamic. You can define what ever variable values you want those objects. The Sound class, on the other hand, is an example of a sealed class.
var array:Array = new Array();
array.customValue = 1; // OK
var sound:Sound = new Sound();
sound.customValue = 2; // Error: Access of possibly undefined property
In ActionScript 2, enforcement of dynamic or sealed classes was handled by the compiler. Because of this, you could work around the restriction of sealed classes using the array access operator to reference variables
// ActionScript 2 workaround
var sound:Sound = new Sound();
sound["customValue"] = 2; // Works
This is no longer the case in ActionScript 3. Sealed classes in ActionScript 3 are enforced not only at compile time, but also runtime.
As you work with different objects in ActionScript, you will need to note which objects are dynamic and which are not. Here is a list of commonly used dynamic classes:
- Object
- Array
- Date
- Dictionary
- Error (and most other Error Classes)
- MovieClip
- RegExp
- StyleSheet
- URLVariables
- XML (and XMLList)
The Value of this
The this
keyword in ActionScript is used to access the current scope, or the object the code in the current block is being run in the context of. Using this
on the timeline will reference the MovieClip instance to which that timeline belongs.
// Main timeline
trace(this); // [object MainTimeline]
In functions, referencing this
references the object in which the current function is defined. Since the same function can be easily defined in multiple objects, a single function can make use of the this
reference and perform actions on different objects based on which object it is being called from.
var joe:Object = new Object();
joe.name = "Joe";
joe.showName = function():void {
trace( this.name);
}
var jane:Object = new Object();
jane.name = "Jane";
jane.showName = joe.showName;
joe.showName (); // traces "Joe"
jane.showName(); // traces "Jane"
Here, there was only one function definition for showName, initially defined to the showName variable in the joe object. That function was then assigned to the jane object, again using the variable name showName �C one function, two references to it in two different objects. The object from which the function is being called determines which object the this
keyword references.
This behavior was consistent for ActionScript 1 and ActionScript 2 for all functions. Now, in ActionScript 3, this is only the case for anonymous functions. Named functions in ActionScript 3 now support method closures, or are bound to the object for which they are initially defined. If the above example can be written again using a named function. Watch what happens when the functions are called from their respective objects.
function showName():void {
trace(this.name);
}
var joe:Object = new Object();
joe.name = "Joe";
joe.showName = showName
var jane:Object = new Object();
jane.name = "Jane";
jane.showName = showName;
joe.showName(); // traces "root1"
jane.showName(); // traces "root1"
It doesn't matter what object the showName function is defined, it's reference to this will always be the main timeline (root1). This is because, as a named function, in ActionScript 3, this will always reference the object instance of the original context of the function definition. This is especially useful for event handling where in, in the past, workarounds had to be used to maintain a valid reference to the instance for which a handler as defined (i.e. using mx.utils.Delegate in ActionScript 2).
Events
Events indicate when something happen. Clicking on a button indicates a "click" event. When an external text file loads into the Flash player, there's a "complete" event indicating that the contents of that text file have been completely read into the player.
Virtually all ActionScript is executed based on events. Event commands written on the timeline in frames can be see as code executed during the event of the Flash Player reading and displaying that frame (this has changed slightly in ActionScript 3 with variable and function definitions which will be covered later).
Events then
For non frame-based actions, most events (specifically mouse and keyboard events) were originally handled within on([event]){} code blocks placed on button symbols.
// Starting with Flash 2 and available for
// ActionScript 1 and 2, a press event
// placed on a selected button symbol
on(press) {
// play timeline in which this button exists
play();
}
Events used with on
(some introduced after Flash 2) include:
- press
- release
- releaseOutside
- rollout
- rollover
- dragOut
- dragOver
- keyPress ["whichKey"]
Flash 5 featured a new kind of event handler that could be added, not to button symbols, but movie clips. This was the onClipEvent([event]{} code block.
// Placed on a selected movie clip symbol
onClipEvent(enterFrame) {
// move this movie clip 5 frames to
// the right every time the Flash player
// draws a frame based on the frame rate
_x += 5;
}
With Flash 5 you could also load XML into the Flash player with the new (at the time) XML object. In order for a programmer to know when the XML has been loaded and parsed, an onLoad event handler would be defined for the XML object. This handler was in the form of a dynamic function definition that could be defined, deleted and changed for the XML object at any time.
// Flash 5 XML onLoad handler
var myXML = new XML();
// event handler called when
// XML has been loaded into myXML
myXML.onLoad = function(success){
// if XML has been loaded and parsed
// successfully, success is true
if (success){
trace(this); // trace XML
}
}
// load the XML into the XML object when
// loaded and parsed, onLoad will be called
myXML.load("xmlFile.xml");
Flash MX (6) greatly improved event handling. Not only were on
code blocks allowed to be used on both movie clips and buttons (as opposed to just buttons) but, Flash MX also allowed dynamic event handlers to be created for buttons and movie clips in the same way the onLoad
event handler was defined for XML objects in Flash 5. Whereas on
and onClipEvent
were static and couldn't be changed during runtime, using these function-based event handlers meant an event could be deleted or redefined as the Flash movie was playing, something especially useful for onEnterFrame events used to handle animation.
// Flash MX onEnterFrame event handler
// assigned for for a movie clip instance
myBall_mc.onEnterFrame = function(){
// move this movie clip to the right
// by 5 pixels every frame
this._x += 5;
// if the x position of this movie clip
// is greater than 200, delete the event handler
if (this._x > 200){
delete this.onEnterFrame;
}
}
More importantly, Flash MX introduced a new concept to Flash called listeners. Listeners are objects with methods (and, later, can include methods or functions only) that listen for and have a handler called as a result of an event. The key concept behind listeners is that you can have more than one event handler associated with any one event. With normal event handlers, like the onLoad event handler with the XML object, you can only define one onLoad function. If you define it again, you will be overwriting the old onLoad and replacing it with the new definition. It was very difficult to have more than one event handler associated with a single event. Listeners solved that.
With listeners, instead of defining an event handler for the object receiving the event, you assigned the event handler to another object �C any other object, and then had that object added to be a listener of the object receiving the event.
// Flash MX Mouse listeners; more than one
// object/handler reacting to the same event
var handler1 = new Object();
handler1.onMouseDown = function(){
trace("Handler 1");
}
var handler2 = new Object();
handler2.onMouseDown = function(){
trace("Handler 2");
}
Mouse.addListener(handler1);
Mouse.addListener(handler2);
// Clicking the mouse once results in the traces:
// Handler 1
// Handler 2
Since both handler1 and handler2 were listeners of the Mouse object, their onMouseDown methods were called as event handlers of the Mouse's onMouseDown event. If you ever wanted to remove an object from being an event listener, you could use removeListener()
.
This was a great concept but was only limited to a few objects including:
- Key
- Mouse
- Selection
- Stage
- TextField
- FStyleFormat
Enter ActionScript 2 with Flash MX 2004 (7). With ActionScript 2 came a new set of components that used an architecture known as V2 ("version 2"). This architecture used a new kind of listener format which was similar to using addListener
but instead of adding objects as listeners of other objects, you listened to specific events from other objects. This used a new method called addEventListener
that was part of a new (V2) class called EventDispatcher. The addEventListener
method accepted not only an object with one or more event handlers, but also a name of the event you wanted to listen for. This not only prevented unnecessary events to be sent to objects that didn't have event handlers for them (e.g. handler1 and handler2 in the previous example received onMouseDown and onMouseUp events from the Mouse object even though they had no event handlers for them), but it also allowed you to use functions as listeners, not just objects with event handlers defined within them. Additionally, an event object was passed to the event handlers to provide information about the event.
// Flash MX 2004/ActionScript 2 button
// component event handlers
// Listener object with event handler
var handlerObject:Object = new Object();
handlerObject.click = function(event:Object):Void {
trace(event.type +": "+ this);
}
// Listener function
function handlerFunction(event:Object):Void {
trace( event.type +": "+ this);
}
// assign to be listeners of
// submit_button for the click event
submit_button.addEventListener("click", handlerObject);
submit_button.addEventListener("click", handlerFunction);
// Clicking the submit_button component:
// click: _level0.submit_button
// click: [object Object]
Because this form of event handling was built into the V2 component architecture (the EventDispatcher class being part of that architecture), you really didn't see it much anywhere else in ActionScript. The core language objects like Mouse and Key still used the older addListener method for handling events. This all changed with ActionScript 3.
Events now
ActionScript 3 completely revamped the way events were handled in ActionScript 3. There are two major themes that define ActionScript 3 events:
- Event handling with a new, native EventDispatcher class
- Support for event propagation with display objects
The EventDispatcher class is not entirely new. It existed, in some form, with the V2 component architecture present in Flash MX 2004 components. But now, with ActionScript 3, EventDispatcher has been made a native part of the ActionScript language and is responsible for essentially all event handling.
ActionScript 3 and Classes
ActionScript 3 is class-based by nature. Classes, if you are not familiar with them, are predetermined definitions for objects in code. An Array object in ActionScript, for example, has a predefined set of properties (variables) and methods (functions) associated with it; properties like length, and methods like push() and pop(). These are all predetermined by an Array class which is defined internally by Flash. Should you want to make your own object definitions, you could make your own class to describe your own type of object. For example, consider the following object created with ActionScript:
// Rectangle object represented in code
var rectangleShape:Object = new Object();
rectangleShape.width = 10;
rectangleShape.height = 20;
rectangleShape.area = function():Number {
return this.width * this.height;
}
This example creates an object called rectangleShape
which has two variables assigned to it, width
and height
, as well as a function called area
which determines the area of the rectangle based on the values of width
and height
. In terms of functionality, this does about everything you need it to as far as rectangles go. But what if you want to make more rectangles? Do you have to through the same definition process? And what if you ever wanted to check to see if a certain variable was assigned to have a rectangle value? In this example, the type of object the rectangleShape is, is Object, not something that specifically indicates it as being a rectangle.
If you would like the rectangle instances to be a certain type, such as the type "RectangleShape" or something similar, then you could define the rectangle object in class and create new rectangles by creating new instances of that class. The definition for rectangleShape as a class could look something like the following in ActionScript 3:
// Defined in an external ActionScript
// file saved as RectangleShape.as
package {
public class RectangleShape {
public var width:Number;
public var height:Number;
public function RectangleShape(width:Number = 0, height:Number = 0){
this.width = width;
this.height = height;
}
public function area():Number {
return width*height;
}
}
}
As a class it would also be defined in a separate ActionScript file (a text file with an .as extension) and saved in a location within the Flash file's classpath �C or a location where Flash would know to look for it when the class is referenced or used in code. Then instead of using a generic Object value to define rectangleShape, you would use the RectangleShape class making a new instance of RectangleShape.
// Code used in Flash
var rectangleShape:RectangleShape = new RectangleShape(10, 20);
Here, not only was creating rectangleShape easier, but it also has a unique type associated with it that can be used to check to see if a certain value is in fact of the type (or originating from the class) RectangleShape.
But getting back to the point, though ActionScript has supported these classes in some respect all the way back to Flash 5 with ActionScript 1, only with ActionScript 3 are you seeing a more true representation of classes. And it just isn't a matter of having the option of creating these things called classes. In ActionScript 3, everything is an instance of a class and all the code you right becomes part of a class definition, even if not written within a separate ActionScript file meant to define a class.
This is important, especially if you are coming from an ActionScript 1 or ActionScript 2 background. Code written for ActionScript 1 and ActionScript 2 was either timeline based or added to button or movie clip selections. Even when a class was defined in ActionScript 1 or ActionScript 2 it was done so on the timeline �C where there was code, there was a timeline. In ActionScript 3, where there is code, there is a class.
So what does this mean for Flash CS3 and ActionScript 3? Does all code have to exist as external class files? Can you still write code on the timeline? What if you don't know, or want to know, anything about classes?
The good news is little has changed in terms of writing code for FLA files in the Flash IDE and you can still write code on the timeline, just as you always have. The compiler that creates published SWF from your FLA file will be able to handle all the technical issues revolving around this new aspect of ActionScript in the background, much in the same way it handles converting ActionScript 2 classes into ActionScript 1 code in the background without you, the user, really knowing. This means you won't have to know anything about classes nor will you need to mess with external class files if you don't want to when working with ActionScript 3 in Flash.
But don't get too excited. This doesn't mean that nothing has changed. In ActionScript 3, no longer can you write code for selections using on()
or onClipEvent()
code blocks and the Var option for text fields is no more leaving you to use TextField.text
instead.
// Code like this defined on objects is
// no longer possible in ActionScript 3
on(press) {
textVar = "value"; // text field Var variables are no more
}
onClipEvent(enterFrame) {
// code
}
Also there's that whole deal with timeline scripts being converted to classes. Though this is mostly hidden from the user with a compile-time conversion, there are a lot of oddities that result from this behavior.
ActionScript and the Timeline
Timelines in Flash consist of one or more frames that contain graphics associated with visual elements displayed on the screen. A timeline with multiple frames will run through those frames as a Flash movie is being viewed showing an animation.
In addition to graphics, timelines can also contain ActionScript (as well as anchors and labels). More specifically, frames within a timeline can contain ActionScript. The code placed in each frame of a timeline gets executed when Flash displays that frame on the screen. With ActionScript 1 and ActionScript 2 Flash was working with a paradigm that depended heavily on the timeline as a foundation for not only animation but also ActionScript. To make a long story short, this model was limiting.
ActionScript 3 broke away from the timeline and instead isolates ActionScript definitions into separate class definitions that have no dependency on the timeline. Take the following ActionScript 2 class.
// ActionScript 2 definition in Example.as
class Example {
public var num:Number;
private var str:String = "text";
public function Example(){
this.num = 1;
}
public function doubleNum():Void {
this.num *= 2;
}
}
A FLA might use this class in frame 1 of the main timeline with the following:
// main timeline of ActionScript 2 FLA
var myExample:Example = new Example();
When compiled and published into a SWF, the SWF gets code that is attached to the timeline and essentially looks like this:
// compiled version
_global.Example = function(){
this.num = 1;
}
Example.prototype.str = "text";
Example.prototype.doubleNum = function(){
this.num *= 2;
}
myExample = new Example();
All ActionScript 2 class definitions, when compiled, end up in the main timeline as ActionScript 1 definitions. And, really, to be more specific, the definitions actually end up in dynamically generated movie clip symbols placed in the library during compile time. Within these movie clips' timelines, however, the definitions are created within an #initclip/