
Learning ActionScript (Part 2)
2.0 Learning the Flash player object model
2.1 Introducing object-oriented programming
Much discussion has been made over the pros and cons of procedural versus object-oriented programming. To touch briefly on this, here is a little background concerning the evolution of ActionScript.
ActionScript started as a sequential programming language, meaning that scripting was limited to a linear sequence of instructions telling Flash what to do in a step-by-step manner. This approach to scripting was not terribly flexible and did not promote reuse.
As the language evolved, it became a procedural programming language. Like sequential programming, procedural programming relied on a step-by-step set of instructions but introduced a more structured, modular approach to scripting. Procedures, otherwise known as functions (or, sometimes, subroutines), could be executed again and again as needed from different parts of a project, without copying and pasting copies of the code into the ongoing sequence of instructions. This modularity promoted reuse, and made the code easier to edit and more efficient.
Scripters in search of an even greater degree of modularity and reuse gravitated toward object-oriented programming. OOP languages create programs that are a collection of objects. Objects are individual instances of classes—collections of code that are self-contained and do not materially alter or disrupt each other. Dividing code into small capsules, appropriately known as encapsulation, is one of the hallmarks of an OOP language. Another important feature of OOP is inheritance, or the ability to derive classes from parent classes, passing on specific characteristics from the parent.
A classic example of OOP structure, and specifically inheritance, defines a set of transportation vehicles. You might start with a generic Vehicle class that includes traits common to all vehicles, such as the basic physics of movement. You might then create three subclasses: GroundVehicle, WaterVehicle, and AirVehicle. These classes would alter or introduce traits specific to ground, water, and air travel, respectively, but not yet be complete enough to represent an actual vehicle. Further derived classes might be Car and Motorcycle (descending from GroundVehicle), Boat, and Submarine (descending from WaterVehicle), and Plane and Helicopter (descending from AirVehicle).Depending on the complexity of your system, you can carry on this process, creating individual models with individual settings for fuel consumption, friction, and so on.
As you can probably imagine, this approach to development adds additional power, flexibility, and prospects for reuse. These benefits, among others, sometimes position object-oriented programming as the best approach to a problem. However, there is a tendency among some programmers to believe that OOP is the best solution to all problems or, effectively, the only solution. This is a faulty assumption.
OOP is often best for very large projects, or for working with a team of programmers, but it can often be overkill for small projects. Additionally, for the uninitiated, it can significantly increase the learning curve, and distract from key topical concepts during your studies. In short, OOP is not always the best tool for the job. Procedural programming still has its place, and Flash CS4 allows you to explore and employ both programming paradigms.
2.1.2 The Document Class
If you decide you would like to start thinking in OOP terms right away, we will show you how to easily take a step in that direction. Flash CS3 introduced a new feature that simplifies associating a main class, or application entry point with your FLA. It is called the document class and it does all the work of instantiating the class for you. This means you don’t need any code in the timeline at all, and can edit all examples in Flash or the external text editor or development environment of your choice. Let’s start with a simulated chapter example that you might use in the timeline. It does nothing more than use the trace() method to place a word into the fOutput panel—an authoring-only panel that accepts text output from your file.
trace(“Flash”);
To create a document class, you’re going to create a kind of wrapper that encloses the trace() method in the correct class syntax.
Create a new ActionScript file (rather than a new FLA document) and type the following document class shell:
1 package {
2 import flash.display.MovieClip;
3 public class Main extends MovieClip {
4 public function Main() {
5
6 }
7 }
8 }
The first line, along with the closing brace in line 8, defines the class’s package. A package is a mandatory structure that ensures your class is known to the compiler. Next, you must import any classes that you need to use in your package.
A document class essentially serves as a shortcut for creating an instance of a movie clip or sprite (a new Flash object that is nothing more than a oneframe movie clip) and adding it to the display list so it can be displayed by Flash Player. (This is true even when there is nothing to display, as in this case.)
All document classes must be derived from either the MovieClip or Sprite class. (Other custom classes that are not document classes do not need to be extended from MovieClip or Sprite if that is not appropriate.) This example uses MovieClip so you must import the MovieClip class, as seen in line 2.
Line 3, along with its closing brace on line 7, is the class definition. Its name is arbitrary but, when naming it, you should follow a few basic rules and conventions. The name should be one word that does not already exist in ActionScript, it should start with an alpha character (rather than a number or other character), and it is typically capitalized. The class must be public, meaning that other classes can access the constructor, and it must extend MovieClip or Sprite, as described previously.
Line 4, along with its closing brace on line 6, is the class constructor. This is the main function that automatically runs when creating an instance of this class. It, too, must be public and must have the same name as the class. Other functions (if any) can, and must, have unique names. All that remains is to add the lone method required in this case. The constructor must trace “Flash” to the Output panel, so add the following to line 8:
public function Main() {
trace(“Flash”);
}
Once finished, you must save the file in the same directory as your FLA file for now. (Later on, you’ll learn how to place your class files in other locations.) You must give the file the same name as the class, but add an .as extension.
Therefore, this file should be named Main.as. Now create a new FLA file, choosing ActionScript 3.0 as its programming language version, and save it in the same directory as your previously created class file. The name of the FLA is unimportant.
Finally, open the Properties Inspector and add the name of your document class, not the name of the document itself, in the Document Class field. In this case, type Main instead of Main.as, as seen in Figure 1-1.
Figure 1-1. Adding a document class to your FLA
Now preview your file. Doing so will create an instance of the Main class (which extends MovieClip and, therefore, behaves like a movie clip) and add it to the display list. The class will trace “Flash” to the output panel, and your test application will be complete.
Hereafter, you can try any of our timeline code in a document class of your own. Initially, you probably won’t know which classes to import or how to make any possible changes to variables or similar structures to conform to the class syntax. However, all the sample code will come with an accompanying class file for testing. You can use those files whenever you wish until you get used to the document class format.
2.2 The String class
2.2.1 Creating strings
The String class is used to represent string (textual) data in ActionScript 3.0. ActionScript strings support both ASCII and Unicode characters. The simplest way to create a string is to use a string literal. To declare a string literal, use straight double quotation mark (“) or single quotation mark (‘) characters. For example, the following two strings are equivalent:
var str1:String = “hello”;
var str2:String = ‘hello’;
You can also declare a string by using the new operator, as follows:
var str1:String = new String(“hello”);
var str2:String = new String(str1);
var str3:String = new String(); // str3 == “”
The following two strings are equivalent:
var str1:String = “hello”;
var str2:String = new String(“hello”);
To use single quotation marks (‘) within a string literal defined with single quotation mark (‘) delimiters, use the backslash escape character (). Similarly, to use double quotation marks (“) within a string literal defined with double quotation marks (“) delimiters, use the backslash escape character (). The following two strings are equivalent:
var str1:String = “That’s ”A-OK””;
var str2:String = ‘That’s “A-OK”’;
You may choose to use single quotation marks or double quotation marks based on any single or double quotation marks that exist in a string literal, as in the following:
var str1:String = “ActionScript 3.0”;
var str2:String = ‘banana’;
Keep in mind that ActionScript distinguishes between a straight single quotation mark (‘) and a left or right single quotation mark (‘ or ‘). The same is true for double quotation marks. Use straight quotation marks to delineate string literals. When pasting text from another source into ActionScript, be sure to use the correct characters.
As the following table shows, you can use the backslash escape character () to define other characters in string literals:
Escape sequence Character
b Backspace
f Form feed
n Newline
r Carriage return
t Tab
unnnn The Unicode character with the character code specified by the hexadecimal number nnnn; for example, u263a is the smiley character.
xnn The ASCII character with the character code specified by the hexadecimal number nn
’ Single quotation mark
” Double quotation mark
Single backslash character
2.2.2 The length property
Every string has a length property, which is equal to the number of characters in the string:
var str:String = “Adobe”;
trace(str.length); // output: 5
An empty string and a null string both have a length of 0, as the following example shows:
var str1:String = new String();
trace(str1.length); // output: 0
str2:String = ‘’;
trace(str2.length); // output: 0
2.2.3 Working with characters in strings
Every character in a string has an index position in the string (an integer). The index position of the first character is 0. For example, in the following string, the character y is in position 0 and the character w is in position 5: “yellow”
You can examine individual characters in various positions in a string using the charAt() method and the charCodeAt()
method, as in this example:
var str:String = “hello world!”;
for (var i:int = 0; i < str.length; i++) {
trace(str.charAt(i), “-”, str.charCodeAt(i));
}
When you run this code, the following output is produced:
h - 104
e - 101
l - 108
l - 108
o - 111
- 32
w - 119
o - 111
r - 114
l - 108
d - 100
! - 33
You can also use character codes to define a string using the fromCharCode() method, as the following example shows:
var myStr:String = String.fromCharCode(104,101,108,108,111,32,119,111,114,108,100,33);
// Sets myStr to “hello world!”
2.2.4 Comparing strings
You can use the following operators to compare strings: <, , and >. These operators can be used with conditional statements, such as if and while, as the following example shows:
var str1:String = “Apple”;
var str2:String = “apple”;
if (str1 < str2) {
trace(“A < a, B < b, C < c, ...”);
}
When using these operators with strings, ActionScript considers the character code value of each character in the string, comparing characters from left to right, as in the following:
trace(“A” < “B”); // true
trace(“A” < “a”); // true
trace(“Ab” < “az”); // true
trace(“abc” < “abza”); // true
Use the == and != operators to compare strings with each other and to compare strings with other types of objects, as the following example shows:
var str1:String = “1”;
var str1b:String = “1”;
var str2:String = “2”;
trace(str1==str1b); // true
trace(str1==str2); // false
var total:uint = 1;
trace(str1==total); // true
2.2.5 Obtaining string representations of other objects
You can obtain a String representation for any kind of object. All objects have a toString() method for this purpose:
var n:Number = 99.47;
var str:String = n.toString();
// str == “99.47”
When using the + concatenation operator with a combination of String objects and objects that are not strings, you do not need to use the toString() method. For details on concatenation, see the next section.
The String() global function returns the same value for a given object as the value returned by the object calling the toString() method.
2.2.6 Concatenating strings
Concatenation of strings means taking two strings and joining them sequentially into one. For example, you can use the + operator to concatenate two strings:
var str1:String = “green”;
var str2:String = “ish”;
var str3:String = str1 + str2; // str3 == “greenish”
You can also use the += operator to the produce the same result, as the following example shows:
var str:String = “green”;
str += “ish”; // str == “greenish”
Additionally, the String class includes a concat() method, which can be used as follows:
var str1:String = “Bonjour”;
var str2:String = “from”;
var str3:String = “Paris”;
var str4:String = str1.concat(“ “, str2, “ “, str3);
// str4 == “Bonjour from Paris”
If you use the + operator (or the += operator) with a String object and an object that is not a string, ActionScript automatically converts the nonstring object to a String object in order to evaluate the expression, as shown in this example:
var str:String = “Area = “;
var area:Number = Math.PI * Math.pow(3, 2);
str = str + area; // str == “Area = 28.274333882308138”
However, you can use parentheses for grouping to provide context for the + operator, as the following example shows:
trace(“Total: $” + 4.55 + 1.45); // output: Total: $4.551.45
trace(“Total: $” + (4.55 + 1.45)); // output: Total: $6
2.2.7 Finding substrings and patterns in strings
Substrings are sequential characters within a string. For example, the string “abc” has the following substrings:
“”, “a”, “ab”, “abc”, “b”, “bc”, “c”.
You can use ActionScript methods to locate substrings of a string.
Patterns are defined in ActionScript by strings or by regular expressions. For example, the following regular expression defines a specific pattern—the letters A, B, and C followed by a digit character (the forward slashes are regular expression delimiters):
/ABCd/
ActionScript includes methods for finding patterns in strings and for replacing found matches with replacement substrings. These methods are described in the following sections.
Regular expressions can define intricate patterns. For more information, see “Using regular expressions” on page 203.
2.2.8 Finding a substring by character position
The substr() and substring() methods are similar. Both return a substring of a string. Both take two parameters. In both methods, the first parameter is the position of the starting character in the given string. However, in the substr() method, the second parameter is the length of the substring to return, and in the substring() method, the second parameter is the position of the character at the end of the substring (which is not included in the returned string). This example shows the difference between these two methods:
var str:String = “Hello from Paris, Texas!!!”;
trace(str.substr(11,15)); // output: Paris, Texas!!!
trace(str.substring(11,15)); // output: Pari
The slice() method functions similarly to the substring() method. When given two non-negative integers as parameters, it works exactly the same. However, the slice() method can take negative integers as parameters, in which case the character position is taken from the end of the string, as shown in the following example:
var str:String = “Hello from Paris, Texas!!!”;
trace(str.slice(11,15)); // output: Pari
trace(str.slice(-3,-1)); // output: !!
trace(str.slice(-3,26)); // output: !!!
trace(str.slice(-3,str.length)); // output: !!!
trace(str.slice(-8,-3)); // output: Texas
You can combine non-negative and negative integers as the parameters of the slice() method.
2.2.9 Finding the character position of a matching substring
You can use the indexOf() and lastIndexOf() methods to locate matching substrings within a string, as the following example shows:
var str:String = “The moon, the stars, the sea, the land”;
trace(str.indexOf(“the”)); // output: 10
Notice that the indexOf() method is case-sensitive.
You can specify a second parameter to indicate the index position in the string from which to start the search, as follows:
var str:String = “The moon, the stars, the sea, the land”
trace(str.indexOf(“the”, 11)); // output: 21
The lastIndexOf() method finds the last occurrence of a substring in the string:
var str:String = “The moon, the stars, the sea, the land”
trace(str.lastIndexOf(“the”)); // output: 30
If you include a second parameter with the lastIndexOf() method, the search is conducted from that index position in the string working backward (from right to left):
var str:String = “The moon, the stars, the sea, the land”
trace(str.lastIndexOf(“the”, 29)); // output: 21
2.2.10 Creating an array of substrings segmented by a delimiter
You can use the split() method to create an array of substrings, which is divided based on a delimiter. For example, you can segment a comma-delimited or tab-delimited string into multiple strings.
The following example shows how to split an array into substrings with the ampersand (&) character as the delimiter:
var queryStr:String = “first=joe&last=cheng&title=manager&StartDate=3/6/65”;
var params:Array = queryStr.split(“&”, 2); // params == [“first=joe”,”last=cheng”]
The second parameter of the split() method, which is optional, defines the maximum size of the array that is returned.
You can also use a regular expression as the delimiter character:
var str:String = “Give met5.”
var a:Array = str.split(/s+/); // a == [“Give”,”me”,”5.”]
For more information, see “Using regular expressions” on page 203 and the ActionScript 3.0 Language & Components Ref.
2.3 Creating and using instances of the Date class
All of the calendar date and time management functions in ActionScript 3.0 are concentrated in the top-level Date class. The Date class contains methods and properties that let you handle dates and times in either Coordinated Universal Time (UTC) or in local time specific to a time zone. UTC is a standard time definition that is essentially the same as Greenwich Mean Time (GMT).
2.3.1 Creating Date objects
The Date class boasts one of the most versatile constructor methods of all the core classes. You can invoke it four different ways.
1. If given no parameters, the Date() constructor returns a Date object containing the current date and time, in local time based on your time zone. Here’s an example:
var now:Date = new Date();
2. If given a single numeric parameter, the Date() constructor treats that as the number of milliseconds since January 1, 1970, and returns a corresponding Date object. Note that the millisecond value you pass in is treated as milliseconds since January 1, 1970, in UTC. However, the Date object shows values in your local time zone, unless you use the UTC-specific methods to retrieve and display them. If you create a new Date object using a single milliseconds parameter, make sure you account for the time zone difference between your local time and UTC. The following statements create a Date object set to midnight on the day of January 1, 1970, in UTC:
var millisecondsPerDay:int = 1000 * 60 * 60 * 24;
// gets a Date one day after the start date of 1/1/1970
var startTime:Date = new Date(millisecondsPerDay);
3. You can pass multiple numeric parameters to the Date() constructor. It treats those parameters as the year, month, day, hour, minute, second, and millisecond, respectively, and returns a corresponding Date object. Those input parameters are assumed to be in local time rather than UTC. The following statements get a Date object set to midnight at the start of January 1, 2000, in local time:
var millenium:Date = new Date(2000, 0, 1, 0, 0, 0, 0);
4. You can pass a single string parameter to the Date() constructor. It will try to parse that string into date or time components and then return a corresponding Date object. If you use this approach, it’s a good idea to enclose the Date()constructor in a try..catch block to trap any parsing errors. The Date() constructor accepts a number of different string formats, as listed in the ActionScript 3.0 Language and Components Reference. The following statement initializes a new Date object using a string value:
var nextDay:Date = new Date(“Mon May 1 2006 11:30:00 AM”);
If the Date() constructor cannot successfully parse the string parameter, it will not raise an exception. However, the resulting Date object will contain an invalid date value.
2.4 Creating and manipulating arrays
Basic variables can contain only one value. If you set a variable to 1 and then set that same variable to 2 in the following line, the value would be reassigned, and the value of the variable would be 2.
However, there are times when you need one variable to contain more than one value. Think of a hypothetical set of groceries, including 50 items. The standard variable approach to this problem would be to define 50 variables and populate each with a grocery item. That is the equivalent of 50 pieces of paper, each with one grocery item written on its face. This is unwieldy and can only be created at author time—at which point the process is fixed—and you’d have to recall and manage all variable names every time you wanted to access the grocery items.
An array equivalent, however, is very much like how we handle this in real life. A list of 50 grocery items is written on one piece of paper. You can add to the list while at the store, cross each item off once it is acquired, and you only have to manage one piece of paper.
Creating an array is quite easy. You can prepopulate an array by setting a variable (typed as an Array) to a comma-separated list of items, surrounded by brackets. You can also create an empty array by using the Array class. Both techniques are illustrated here:
var myArray:Array = [1, 2, 3];
var yourArray:Array = new Array();
In both cases, you can add to, or remove from, the array at runtime. For example, you can add a value to an array using the push() method, which pushes the value into the array at the end. In short, a method is an action performed by an object—in this case adding something to the array—and will be discussed in detail in the next chapter. You can remove an item from the end of an array using the pop() method.
var myArray:Array = new Array();
myArray.push(1);
trace(myArray);
// 1 appears in the Output panel
myArray.push(2);
// the array now has two items: 1, 2
trace(myArray.pop());
// the pop() method removes the last item, displaying its value of 2
trace(myArray);
// the lone remaining item in the array, 1, is displayed
There are a dozen or so other array methods, allowing you to add to or remove from the front of an array, sort its contents, check for the position of a found item within the array, compare each value against a control value, and more.
You can also add to or retrieve values from locations within the array, by using brackets and including the index, or position, of the array you need. To do so, you must understand that ActionScript uses zero-based arrays, which means that the first value is at position 0, the second is at position 1, the next at position 2, and so on. As an example, to retrieve the existing fifth value from an array, you must request the item at position 4.
var myArray:Array = [“a”, “b”, “c”, “d”, “e”];
trace(myArray[4]);
//”e” appears in the Output panel
There are other kinds of arrays, such as multidimensional arrays (arrays within arrays that can resemble database structures) and associative arrays (which store not only linear values, but also a linear pair of items—the value and a property name to describe that value), for example. However, due to space constraints, we’ve focused on the most common array type: the linear array. Any other uses of array structures will be highlighted in future chapters.