BUY THIS BOOK
Add to Cart

Print Book $24.95


Safari Books Online

What is this?

Add to UK Cart

Print Book £14.95

What is this?

Illustrations with Photoshop: A Designer's Notebook
Illustrations with Photoshop: A Designer's Notebook

Translated by William Rodarmor
Price: $24.95 USD
£14.95 GBP

Cover | Table of Contents | Sample Chapter


Table of Contents

Chapter 1: A Gentle Introduction for Non-Programmers
I'm going to teach you to talk to Flash.
Not just to program in Flash but to say things to it and to listen to what it has to say in return. This is not a metaphor or simply a rhetorical device. It's a philosophical approach to programming.
Programming languages are used to send information to and receive information from computers. They are collections of vocabulary and grammar used to communicate, just like human languages. Using a programming language, we tell a computer what to do or ask it for information. It listens, tries to perform the requested actions, and gives responses. So while you may think you are reading this book in order to "learn to program," you are actually learning to communicate with Flash. But, of course, Flash doesn't speak English, French, German, or Cantonese. Flash's native language is ActionScript, and you're going to learn to speak it.
Learning to speak a computer language is sometimes considered synonymous with learning to program. But there is more to programming than learning a language's syntax. What would it be like if Flash could speak English—if we didn't need to learn ActionScript in order to communicate with it?
What would happen if we were to say, "Flash, make a ball bounce around the screen?"
Flash couldn't fulfill our request because it doesn't understand the word "ball." Okay, okay, that's just a matter of semantics. What Flash expects us to describe is the objects in the world it knows: movie clips, buttons, frames, and so on. So, let's rephrase our request in terms that Flash recognizes and see what happens: "Flash, make the movie clip named ball_one bounce around the screen."
Flash still can't fulfill our request without more information. How big should the ball be? Where should it be placed? In which direction should it begin traveling? How fast should it go? Around which part of the screen should it bounce? For how long? In two dimensions or three? Hmm . . . we weren't expecting all these questions. In reality, Flash doesn't ask us these questions. Instead, when Flash can't understand us, it just doesn't do what we want it to, or it yields an error message. For now, we'll pretend Flash asked us for more explicit instructions, and reformulate our request as a series of steps:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Some Basic Phrases
On the first day of any language school you'd expect to learn a few basic phrases ("Good day," "How are you," etc.). Even if you're just memorizing a phrase and don't know what each word means, you can learn the effect of the phrase and can repeat it to produce that effect. Once you've learned the rules of grammar, expanded your vocabulary, and used the words from your memorized phrases in multiple contexts, you can understand your early phrases in a richer way. The rest of this chapter will be much like that first day of language school—you'll see bits and pieces of code, and you'll be introduced to some fundamental programming grammar. The rest of the book will build on that foundation. You may want to come back to this chapter when you've finished the book to see just how far you've traveled.
For our first exercise, we'll learn how to add four simple lines of code to a Flash movie. Nearly all ActionScript programming takes place in the Actions panel. Any instructions we add to the Actions panel are carried out by Flash when our movie plays. Open the Actions panel now by following these steps:
  1. Launch Flash with a new blank document.
  2. On the main timeline, select frame 1 of layer 1.
  3. Select Window → Actions.
The Actions panel is divided into two sections: the Script pane (on the right) and the Toolbox pane (on the left). The Script pane houses all our code. The Toolbox pane provides us with quick access to the Actions, Operators, Functions, Properties, and Objects of ActionScript. You'll likely recognize the Basic Actions, shown in Figure 1.1, from prior Flash versions.
Figure 1.1: Flash 5 Basic Actions
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Further ActionScript Concepts
You've already been introduced to many of the fundamental elements that make up ActionScript: data, variables, operators, statements, functions, and arguments. Before we delve deeper into those topics, let's sketch out the rest of ActionScript's core features.
To most computer users, a program is synonymous with an application, such as Adobe Photoshop or Macromedia Dreamweaver. Obviously, that's not what we're building when we program in Flash. Programmers, on the other hand, define a program as a collection of code (a "series of statements"), but that's only part of what we're building.
A Flash movie is more than a series of lines of code. Code in Flash is intermingled with Flash movie elements, like frames and buttons. We attach our code to those elements so that it can interact with them.
In the end, there really isn't such a thing as a Flash "program" in the classic sense of the term. Instead of complete programs written in ActionScript, we have scripts : code segments that give programmatic behavior to our movie, just as JavaScript scripts give programmatic behavior to HTML documents. The real product we're building is not a program but a complete movie (including its code, timelines, visuals, sound, and other assets).
Our scripts include most of what you'd see in traditional programs without the operating-system-level stuff you would write in languages like C++ or Java to place graphics on the screen or cue sounds. We're spared the need to manage the nuts 'n' bolts of graphics and sound programming, which allows us to focus most of our effort on designing the behavior of our movies.
The statements of a script, as we've learned, contain the script's instructions. But most instructions are pretty useless without data. When we set a variable, for example, we assign some data as its value. When we use the
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Building a Multiple-Choice Quiz
Now that we've explored the basic principles of ActionScript, let's apply those principles in the context of a real Flash movie. We'll start our applied study of Flash programming by creating a multiple-choice quiz using very simple programming techniques, most of which you've already learned. We'll revisit our quiz in later chapters to see how it can be improved after learning more advanced programming concepts. We'll eventually make the code more elegant so that it's easier to extend and maintain, and we'll add more features to our quiz so that it can easily handle any number of questions.
The finished .fla file for this quiz may be found in the online Code Depot. This is a lesson in Flash programming, not Flash production. It is assumed that you are already comfortable creating and using buttons, layers, frames, keyframes, and the Text tool. The quiz shows real-world applications of the following aspects of ActionScript programming:
  • Variables
  • Controlling the playhead of a movie with functions
  • Button event handlers
  • Simple conditionals
  • Text field variables for on-screen display of information
Our quiz, part of which is shown in Figure 1.4, will have only two questions. Each question comes with three multiple-choice answers. Users submit their answers by clicking the button that corresponds to their desired selections. The selections are recorded in a variable so that they may be used to grade the user's score. When all the questions have been answered, the number of correct answers is tallied and the user's score is displayed.
Figure 1.4: A Flash quiz
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Onward!
So how does it feel? You've learned a bunch of phrases, some grammar, some vocabulary, and even had a drawn-out conversation with Flash (the multiple-choice quiz). Quite a rich first day of language school, I'd say.
As you can see, there's a lot to learn about ActionScript, but you can also do quite a bit with just a little knowledge. Even the amount you know now will give you plenty to play around with. Over the rest of this book, we'll reinforce the fundamentals you've learned by exploring them in more depth and showing them in concert with real examples. Of course, we'll also cover some topics that haven't even been introduced yet.
Remember: think communication, think cooperation, and speak clearly. And if you find yourself doing any fantastically engaging work or art that you'd like to share with others, send it over to me at http://www.moock.org/webdesign/flash/contact.html.
Now that you have a practical frame of reference, you'll be better able to appreciate and retain the foundational knowledge detailed over the next few chapters. It will give you a deeper understanding of ActionScript, enabling you to create more complex movies.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 2: Variables
In a typical scripted movie, we have to track and manipulate everything from frame numbers to a user's password to the velocity of a photon torpedo fired from a spaceship. In order to manage and retrieve all that information, we need to store it in variables, the primary information-storage containers of ActionScript.
A variable is a like a bank account that, instead of holding money, holds information (data). Creating a new variable is like setting up a new account; we establish a place to store something we'll need in the future. And just as every bank account has an account number, every variable has a name associated with it that is used to access the data in the variable.
Once a variable is created, we can put new data into it as often as we want—much like depositing money into an account. Or we can find out what's in a variable using the variable's name—much like checking an account balance. If we no longer need our variable, we can "close the account" by deleting the variable.
The key feature to note is that variables let us refer to data that either changes or is calculated when a movie plays. Just as a bank account's number remains the same even though the account balance varies, a variable's name remains fixed even though the data it contains may change. Using that fixed reference to access changing content, we can perform complex calculations, keep track of cards in a card game, save guest book entries, or send the playhead to different locations based on changing conditions.
Is that a gleam of excitement I see in your eye? Good, I thought I might have lost you with all that talk about banks. Let's start our exploration of variables by seeing how to create them.
Creating a variable is called declaration. Declaration is the "open an account" step of our bank metaphor, where we formally bring the variable into existence. When a variable is first declared, it is empty—a blank page waiting to be written upon. In this state, a variable contains a special value called
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Creating Variables (Declaration)
Creating a variable is called declaration. Declaration is the "open an account" step of our bank metaphor, where we formally bring the variable into existence. When a variable is first declared, it is empty—a blank page waiting to be written upon. In this state, a variable contains a special value called undefined (indicating the absence of data).
To declare a new variable, we use the var statement. For example:
var speed;
var bookTitle;
var x;
The word var tells the interpreter that we're declaring a variable, and the text that follows, such as speed, bookTitle, or x, becomes our new variable's name. We can create variables anywhere we can attach code: on a keyframe, a button, or a movie clip.
We can also declare several variables with one var statement, like this:
var x, y, z;
However, doing so impairs our ability to add comments next to each variable.
Once a variable has been created, we may assign it a value, but before we learn how to do that, let's consider some of the subtler details of variable declaration.
Many programming languages require variables to be declared before data may be deposited into them; failure to do so would cause an error. ActionScript is not that strict. If we assign a value to a variable that does not exist, the interpreter will create a new variable for us. The bank, to continue that analogy, automatically opens an account when you try to make your first deposit.
This convenience comes at a cost, though. If we don't declare our variables ourselves, we have no central inventory to consult when examining our code. Furthermore, explicitly declaring a variable with a var statement can sometimes yield different results than allowing a variable to be declared implicitly (i.e., automatically). It's safest to declare first and use later (i.e., explicit declaration), as shown throughout this book.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Assigning Variables
Now comes the fun part—putting some data into our variables. If you're still playing along with the bank analogy, this is the "deposit money into our account" step. To assign a variable a value, we use:
               variableName = value;
where variableName is the name of a variable, and value is the data we're assigning to that variable. Here's an applied example:
bookTitle = "ActionScript: The Definitive Guide";
On the left side of the equal sign, the word bookTitle is the variable's name (its identifier). On the right side of the equal sign, the phrase "ActionScript: The Definitive Guide" is the variable's value —the datum you're depositing. The equal sign itself is called the assignment operator. It tells Flash that you want to assign (i.e., deposit) whatever is on the right of the equal sign to the variable shown on the left. If the variable on the left doesn't exist yet, Flash creates it (though relying on the interpreter to implicitly create variables isn't recommended).
Here are two more variable assignment examples:
speed = 25;
output = "thank you";
The first example assigns the integer 25 to the variable speed, showing that variables can contain numbers as well as text. We'll see shortly that they can contain other kinds of data as well. The second example assigns the text "thank you" to the variable output. Notice that we use straight double quotation marks (" ") to delimit a text string in ActionScript.
Now let's look at a slightly more complicated example that assigns y the value of the expression 1 + 5:
y = 1 + 5;
When the statement y = 1 + 5; is executed, 1 is first added to 5, yielding 6, and then 6 is assigned to y. The expression on the right side of the equal sign is evaluated (calculated or resolved) before setting the variable on the left side equal to that result. Here we assign an expression that contains the variable y to another variable, z:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Changing and Retrieving Variable Values
After we've created a variable, we may assign and reassign its value as often as we like, as shown in Example 2.1.
Example 2.1. Changing Variable Values
var firstName;                   // Declare the variable firstName
firstName = "Graham";            // Set the value of firstName
firstName = "Gillian";           // Change the value of firstName
firstName = "Jessica";           // Change firstName
                   again
firstName = "James";             // Change firstName
                   again
var x = 10;                      // Declare x and assign a numeric value
x = "loading...please wait...";  // Assign x a text value
Notice that we changed the variable x's datatype from numeric to text data by simply assigning it a value of the desired type. Some programming languages don't allow the datatype of a variable to change but ActionScript does.
Of course, creating variables and assigning values to them is useless if you can't retrieve the values later. To retrieve a variable's value, simply use the variable's name wherever you want its value to be used. Anytime a variable's name appears (except in a declaration or on the left side of an assignment statement), the name is converted to the variable's value. Here are some examples:
newX = oldX + 5;  // Set newX to the value of oldX plus 5
ball._x = newX;   // Set the horizontal position of the
                  // ball movie clip to the value of newX
trace(firstName); // Display the value of firstName in the Output window
Note that in the expression ball._x, ball is a movie clip's name, and the ._x indicates its x-coordinate property (i.e., horizontal position on stage). We'll learn more about properties later. The last line, trace(firstName), displays a variable's value while a script is running, which is handy for debugging your code.
Occasionally we may wish to verify that a variable has been assigned a value before we make reference to it. As we learned earlier, a variable that has been declared but never assigned a value contains the special "non-value,"
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Types of Values
The data we use in ActionScript programming comes in a variety of types. So far we've seen numbers and text, but other types include Booleans, arrays, functions, and objects. Before we cover each datatype in detail, let's examine some datatype issues that specifically relate to variable usage.
Any ActionScript variable can contain any type of data, which may seem unremarkable, but the ability to store any kind of data in any variable is actually a bit unusual. Languages like C++ and Java use typed variables; each variable can accept only one type of data, which must be specified when the variable is declared. ActionScript variables are automatically typed—when we assign data to a variable, the interpreter sets the variable's datatype for us.
Not only can ActionScript variables contain any datatype, they can also dynamically change datatypes. If we assign a variable a new value that has a different type than the variable's previous value, the variable is automatically retyped. So the following code is legal in ActionScript:
x = 1;                   // x is a number
x = "Michael";           // x is now a string
x = [4, 6, "hello"];     // x is now an array
x = 2;                   // x is a number again
In languages like C++ or Java that do not support automatic retyping, data of the wrong type would be converted to the variable's existing datatype (or would cause an error if conversion could not be performed). Automatic and dynamic typing have some important ramifications that we'll consider in the following sections.
In some contexts, ActionScript expects a specific type of data. If we use a variable whose value does not match the expected type, the interpreter attempts to convert the data. For example, if we use a text variable where a number is needed, the interpreter will try to convert the variable's text value to a numeric value for the sake of the current operation. In Example 2.2,
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Variable Scope
Earlier we learned how to create variables and retrieve their values using variables attached to a single frame of the main timeline of a Flash document. When a document contains multiple frames and multiple movie clip timelines, variable creation and value retrieval becomes a little more complicated.
To illustrate why, let's consider several scenarios.
Suppose we were to create a variable, x, in frame 1 of the main timeline. After creating x, we set its value to 10:
var x;
x = 10;
Then, in the next frame (frame 2), we attach the following code:
trace(x);
When we play our movie, does anything appear in the Output window? We created our variable in frame 1, but we're attempting to retrieve its value in frame 2; does our variable still exist? Yes.
When you define a variable on a timeline, that variable is accessible from all the other frames of that timeline.
Suppose we create and set x as we did in Scenario 1, but instead of placing the variable-setting code on frame 1 directly, we place it on a button in frame 1. Then, on frame 2, we attach the same code as before:
trace(x);
Does Scenario 2 also work? Yes. Because x is attached to our button, and our button is attached to the main timeline, our variable is indirectly attached to the main timeline. We may, therefore, access the variable from frame 2 as we did before.
Suppose we create a variable named secretPassword on frame 1 of the main timeline. When the movie plays, the user must guess the password in order to gain access to a special section of the movie.
In addition to declaring secretPassword on frame 1, we create a function that compares the user's guess to the real password. Here's our code:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Some Applied Examples
We've had an awful lot of variable theory. How about showing some of these concepts in use? The following examples provide three variable-centric code samples. Refer to the comments for an explanation of the code.
Example 2.6 chooses a random destination for the playhead of a movie.
Example 2.6. Send the Playhead to a Random Frame on the Current Timeline
var randomFrame;            // Stores the randomly picked frame number
var numFrames;              // Stores the total number of frames on the timeline
numFrames = _totalframes;   // Assign _totalframes property to numFrames

// Pick a random frame
randomFrame = Math.floor(Math.random( ) * numFrames + 1);

gotoAndStop(randomFrame);   // Send playhead to chosen random frame
Example 2.7 determines the distance between two clips. A working version of this example is available from the online Code Depot.
Example 2.7. Calculate the Distance Between Two Movie Clips
var c;         // A convenient reference to the circle clip object
var s;         // A convenient reference to the square clip object
var deltaX;    // The horizontal distance between c and s
var deltaY;    // The vertical distance between c and s
var dist;      // The total distance between c and s

c = _root.circle;       // Get reference to the circle clip
s = _root.square;       // Get reference to the square clip
deltaX = c._x - s._x;   // Compute the horizontal distance between the clips
deltaY = c._ y - s._ y;   // Compute the vertical distance between the clips

// The distance is the root of (deltaX squared plus deltaY squared).
dist = Math.sqrt((deltaX * deltaX) + (deltaY * deltaY));

// Tidy references are much more readable than the alternative:
dist = Math.sqrt(((_root.circle._x - _root.square._x) * (_root.circle._x - 
_root.square._x)) + ((_root.circle._ y - _root.square._ y) * (_root.circle._ y - 
_root.square._ y)));
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Onward!
Now that we know all there is to know about storing information in variables, it's time we learn something more about the content that variables store: data. Over the next three chapters, we'll learn what data is, how it can be manipulated, and why it's an essential part of nearly everything we build with ActionScript.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 3: Data and Datatypes
Having worked with variable values in Chapter 2, we've already had a casual introduction to data, the information we manipulate in our scripts. In this chapter, we'll explore data in more depth, learning how ActionScript defines, categorizes, and stores data. We'll also see how to create and classify data.
In the broadest sense, data is anything that can be stored by a computer, from words and numbers to images, video, and sound. All computer data is stored as a sequence of ones and zeros, which you might recognize from high-tech marketing materials:
010101010101010110101011011010101010101010000010101010101011010101010
101010101010101011101010101010101010101010101010111110101010101010101
010101010101010101010101011101010101010101010101010101010101010101010
Data is information in its crude state—raw and meaningless. Information, on the other hand, has meaning. Consider, for example, the number 8008898969. As raw data it isn't very meaningful, but when we classify it semantically as the telephone number (800) 889-8969, the data becomes useful information.
In this chapter we'll see how to add meaning to raw computer data so that it becomes human-comprehensible information.
How do we store information as raw data in a computer without losing meaning? By categorizing our data and defining its datatype, we give it context that defines its meaning.
For example, suppose we have three numbers: 5155534, 5159592, and 4593030. By categorizing our data—as, say, a phone number, fax number, and parcel tracking number—the context (and, hence, the meaning) of our data is preserved. When categorized, each of the otherwise-nondescript seven-digit numbers becomes meaningful.
Programming languages use datatypes to provide rudimentary categories for our data. For example, nearly all programming languages define datatypes to store and manipulate text (a.k.a. strings) and numbers. To distinguish between multiple numbers, we can use well-conceived variable names, such as
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Data Versus Information
In the broadest sense, data is anything that can be stored by a computer, from words and numbers to images, video, and sound. All computer data is stored as a sequence of ones and zeros, which you might recognize from high-tech marketing materials:
010101010101010110101011011010101010101010000010101010101011010101010
101010101010101011101010101010101010101010101010111110101010101010101
010101010101010101010101011101010101010101010101010101010101010101010
Data is information in its crude state—raw and meaningless. Information, on the other hand, has meaning. Consider, for example, the number 8008898969. As raw data it isn't very meaningful, but when we classify it semantically as the telephone number (800) 889-8969, the data becomes useful information.
In this chapter we'll see how to add meaning to raw computer data so that it becomes human-comprehensible information.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Retaining Meaning with Datatypes
How do we store information as raw data in a computer without losing meaning? By categorizing our data and defining its datatype, we give it context that defines its meaning.
For example, suppose we have three numbers: 5155534, 5159592, and 4593030. By categorizing our data—as, say, a phone number, fax number, and parcel tracking number—the context (and, hence, the meaning) of our data is preserved. When categorized, each of the otherwise-nondescript seven-digit numbers becomes meaningful.
Programming languages use datatypes to provide rudimentary categories for our data. For example, nearly all programming languages define datatypes to store and manipulate text (a.k.a. strings) and numbers. To distinguish between multiple numbers, we can use well-conceived variable names, such as phoneNumber and faxNumber. In more complex situations, we can create our own custom data categories with objects and object classes as covered later. Before we think about making our own data categories, let's see which categories come built into ActionScript.
When programming, we may want to store a product name, a background color, or the number of stars to be placed in a night sky. We use the following ActionScript datatypes to store our data:
  • For text sequences like "hi there," ActionScript provides the string datatype. A string is a series of characters (alphanumerics and punctuation).
  • For numbers, such as 351 and 7.5, ActionScript provides the number datatype. Numbers are used for counting and for mathematical equations.
  • For logical decisions, ActionScript provides the Boolean datatype. With Boolean data, we can represent or record the status of some condition or the result of some comparison. Boolean data has only two legal values:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Creating and Categorizing Data
There are two ways to create a new datum with ActionScript, both methods requiring the use of expressions—phrases of code that represent data in our scripts.
A literal expression (or literal for short) is a series of letters, numbers, and punctuation that is the datum. A data literal is a verbatim description of data in a program's source code. This contrasts with a variable, which is a container that merely holds a datum. Each datatype defines its own rules for the creation of literals. Here are some examples of literals:
"loading...please wait"  // A string literal
1.51                     // A numeric literal
["jane", "jonathan"]     // An array literal
Note that movie clips cannot be represented by literals, but are referred to by instance names.
We can also generate data programmatically with a complex expression. Complex expressions represent data as a phrase of code with a value that must be calculated or computed, not taken literally. The calculated value is the datum being represented. For example, each of these complex expressions results in a single datum:
1999 + 1       // Yields the datum 2000
"hi " + "ma!"  // Yields the datum "hi ma!"
firstName      // Yields the value of the variable firstName
_currentframe  // Yields the frame number of the playhead's current position
new Date( )     // Yields a new Date object with the current date and time
Notice that an individual literal expression like 1999 or 1 can be a valid part of a larger complex expression, as in 1999 + 1.
Whether we use a literal expression or a complex expression to create data, we must store every datum that we want to use later. The result of the expression "hi" + "ma!" is lost unless we store it, say, in a variable. For example:
// This datum is fleeting, and dies immediately after it's created
"hi " + "ma";

// This datum is stored in a variable and can be
// accessed later via the variable 
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Datatype Conversion
Take a closer look at the example from the previous section. In that example, each datum—"1" and 2—belonged to its own datatype; the first was a string and the second a number. We saw that the interpreter joined the two values together to form the string "12". Note that the interpreter first had to convert the number 2 into the string "2". Only after that automatic conversion was performed could the value "2" be joined (concatenated) to the string "1".
Datatype conversion simply means changing the type of a datum. Not all datatype conversions are automatic; we may also change a datum's type explicitly in order to override the default datatyping that ActionScript would otherwise perform.
Whenever we use a value in a context that does not match its datatype, the interpreter attempts a conversion. That is, if the interpreter expects data of type A, and we provide data of type B, the interpreter will attempt to convert our type B data into type A data. For example, in the following code we use the string "Flash" as the righthand operand of the subtraction operator. Since only numbers may be used with the subtraction operator, the interpreter attempts to convert the string "Flash" into a number:
999 - "Flash";
Of course, the string "Flash" can't be successfully converted into any legitimate number, so it is converted into the special numeric data value NaN (i.e., Not-a-Number). NaN is a legal value of the number datatype, intended specifically to handle such a situation. With "Flash" converted to NaN, our expression ends up looking like this to the interpreter (though we never see this internal step):
999 - NaN;
Both operands of the subtraction operator are now numbers, so the operation can proceed: 999 - NaN yields the value NaN, which is the final value of our expression.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Primitive Data Versus Composite Data
So far we've been working mostly with numbers and strings, which are the most common primitive datatypes. Primitive datatypes are the basic units of a language; each primitive value contains a single datum (as opposed to an array of multiple items) and describes that datum literally. Primitive data is very straightforward.
ActionScript supports these primitive datatypes: number, string, boolean, undefined, and null. ActionScript does not have a separate single-character datatype (i.e., char) as found in C/C++.
Primitive datatypes are, as their name suggests, simple. They can hold text messages, frame numbers, movie clip size values, and so on, but they don't readily accommodate higher levels of complexity. For more elaborate data handling—such as simulating the physics of a dozen bouncing balls or managing a quiz with 500 questions and answers—we turn to composite datatypes. Using composite data, we can manage multiple pieces of related data as a single datum.
ActionScript supports the following composite datatypes: array, object, and movieclip. Functions are technically a type of object and are therefore considered composite data, but we rarely manipulate them as such. See Chapter 9, for more about functions as a datatype.
Whereas a single number is a primitive datum, a list (i.e., an array) of multiple numbers is a composite datum. Here's a practical example of how composite datatypes are useful: Suppose we wanted to track the profile of a customer named Derek. We could create a series of variables that store Derek's attributes as primitive values, like this:
var custName = "Derek";
var custTitle = "Coding Genius";
var custAge = 30;
var custPhone = "416-222-3333";
However, this format gets pretty cumbersome once we add even a few more customers. We're forced to use sequentially named variables to keep track of everything—cust1Name, cust2Name, cust1Title, cust2Title, and so on. Yuck! But if we use an array, we can store our information much more efficiently:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Onward!
We've been introduced to data in ActionScript, and we're ready for deeper study. In Chapter 4, we'll study the number, string, boolean, undefined, and null datatypes. In Chapter 5, we'll learn how to manipulate data. In later chapters, we'll study the complex datatypes, such as movieclips, arrays and objects.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 4: Primitive Datatypes
Primitive data consists of simple characters or keywords such as the numbers 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, or the strings "a", "b", "c". As we learned in the previous chapter, the primitive datatypes supported by ActionScript are number, string, boolean, undefined, and null. In this chapter we'll learn how to define, examine, and change data of each type.
Numbers are used for counting, mathematics, and to keep track of numeric properties in our movies (like the current frame of a movie clip or its location on the Stage). Let's see how numbers are defined and manipulated in ActionScript.
Most programming languages distinguish between two kinds of numbers: integers and floating-point numbers. An integer is a whole number that has no fractional component. Integers can be positive or negative and include the number 0. Floating-point numbers ( floats for short) can include a fractional value represented after a decimal point, as in 0.56, 199.99, and 3.14159. So 1, 34523, -3, 0, and -9999999 are integers, but 223.45, -0.56, and 1/4 are floats.
We learned earlier that a literal is a direct representation of a single, fixed data value. The number type supports three kinds of literals: integer literals, floating-point literals, and special numeric values. The first two literal categories represent real numbers (numbers that have a fixed mathematical value); the third category comprises values that represent numeric concepts such as infinity.
Integer literals such as 1, 2, 3, 99, and -200, must follow these rules:
  • Integers may not contain a decimal point or fractional value.
  • Integers must not exceed the minimum or maximum legal numeric values of ActionScript. See also the
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The Number Type
Numbers are used for counting, mathematics, and to keep track of numeric properties in our movies (like the current frame of a movie clip or its location on the Stage). Let's see how numbers are defined and manipulated in ActionScript.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Integers and Floating-Point Numbers
Most programming languages distinguish between two kinds of numbers: integers and floating-point numbers. An integer is a whole number that has no fractional component. Integers can be positive or negative and include the number 0. Floating-point numbers ( floats for short) can include a fractional value represented after a decimal point, as in 0.56, 199.99, and 3.14159. So 1, 34523, -3, 0, and -9999999 are integers, but 223.45, -0.56, and 1/4 are floats.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Numeric Literals
We learned earlier that a literal is a direct representation of a single, fixed data value. The number type supports three kinds of literals: integer literals, floating-point literals, and special numeric values. The first two literal categories represent real numbers (numbers that have a fixed mathematical value); the third category comprises values that represent numeric concepts such as infinity.
Integer literals such as 1, 2, 3, 99, and -200, must follow these rules:
  • Integers may not contain a decimal point or fractional value.
  • Integers must not exceed the minimum or maximum legal numeric values of ActionScript. See also the MIN_VALUE and MAX_VALUE properties of the Number object in Part III, for a discussion of legal values.
  • Base-10 integer numbers must not start with a leading zero (e.g., 002, 000023, and 05).
Not all integer values are base-10 (i.e., decimal) integers. ActionScript also supports base-8 (octal) and base-16 (hexadecimal) numeric literals. For a primer on decimal, octal, and hexadecimal numbers, see:
http://www.moock.org/asdg/technotes
We use a leading zero to indicate an octal number. For example, to represent the octal number 723 in ActionScript, we use:
0723  // 467 in decimal (7*64 + 2*8 + 3*1)
To indicate a hexadecimal (hex for short) literal integer, we put 0x (or 0X) in front of the number, such as:
0x723  // 1827 in decimal (7*256 + 2*16 + 3*1)
0xFF   //  255 in decimal (15*16 + 15*1)
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Working with Numbers
We can manipulate numbers by combining them with operators to form mathematical expressions, and by calling built-in functions to perform complex mathematical operations.
Basic arithmetic—addition, subtraction, multiplication, and division—is accomplished using the +, -, *, and / operators. Operators can be used with any numeric literals or data containers such as variables. Mathematical expressions are evaluated in the order determined by the precedence of the operators as shown in Table 5.1. For example, multiplication is performed before addition. All of these are legitimate uses of mathematical operators:
x = 3 * 5;            // Assign the value 15 to x
x = 1 + 2 - 3 / 4;    // Assign the value 2.25 to x

x = 56;
y = 4 * 6 + x;        // Assign the value 80 to y
y = x + (x * x) / x;  // Assign the value 112 to y
               
To perform advanced math, we use the built-in mathematical functions of the Math object. For example:
Math.abs(x)       // Absolute value of x
Math.min(x, y)    // The smaller of the values x and y
Math.pow(x, y)    // x raised to the power y
Math.round(x)     // x rounded to the nearest integer
The math functions return values that we use in expressions, just as we use real numbers. For example, suppose we want to simulate a six-sided die. We can use the random( ) function to retrieve a random float between and 1:
dieRoll = Math.random( );
Then we multiply that value by 6, giving us a float between and 5.999, to which we add 1:
dieRoll = dieRoll * 6 + 1;  // Sets dieRoll to a number between 1 and 6.999
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The String Type
String is the datatype used for textual data (letters, punctuation marks, and other characters). A string literal is any combination of characters enclosed in quotation marks:
"asdfksldfsdfeoif"  // A frustrated string
"greetings"         // A friendly string
"moock@moock.org"   // A self-promotional string
"123"               // It may look like a number, but it's a string
'singles'           // Single quotes are acceptable too
Before we see how to form string literals, let's examine which characters are permitted in strings.
Like all computer data, text characters are stored internally using a numeric code. They are encoded for storage and decoded for display using a character set, which maps (i.e., relates) characters to their numeric codes. Character sets vary for different languages and alphabets. Older Western applications use some derivative of ASCII, a standard character set that includes only 128 characters—the English alphabet, numbers, and basic punctuation marks. Modern applications support a family of character sets known collectively as ISO-8859. Each of the ISO-8859 character sets encodes the standard Latin alphabet (`A' to `Z') plus a varying set of letters needed in the target languages. ActionScript uses ISO-8859-1, also known as Latin 1, as its primary character map.
The Latin 1 character set accommodates most Western European languages—French, German, Italian, Spanish, Portuguese, and so on—but not languages such as Greek, Turkish, Slavic, and Russian. Unicode, the preferred international standard for character encoding that maps up to a million characters, is not supported in ActionScript (support for Unicode would greatly increase the Flash Player size). However, ActionScript does support a second character set for Japanese characters called Shift-JIS. When working with text in ActionScript, we can use any character from Latin 1 or Shift-JIS.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Working with Strings
By manipulating strings we can program anything from a user-input validator to a word-scramble game. With a little ingenuity, we can make neat visual text effects and other fun stuff.
We can manipulate strings with both operators and built-in functions. String operators can join multiple strings together or compare the characters of two strings. Built-in functions can examine a string's properties and contents, extract a portion of a string, check a character's code point, create a character from a code point, change the case of the characters in a string, and even turn a string into a variable or property name.
Joining strings together (creating a new string from two or more strings) is called concatenation. As seen earlier, we can concatenate two strings with the plus operator (+), like this:
"Macromedia" + "Flash"
That line of code yields the single string value "MacromediaFlash". Oops! We forgot to put a space between the words. To add the space, we can insert it within the quotes that define one of the strings, such as:
"Macromedia " + "Flash"  // Yields "Macromedia Flash"
But that's not always practical. In most cases we don't want to add a space to a company or a product name. So instead, we join three strings together, the middle one of which is simply an empty space:
"Macromedia" + " " + "Flash"   // Also yields "Macromedia Flash"
Note that the space character is not the same as the empty string we saw earlier because the empty string has no characters between the quotes.
We can also concatenate variables that contain string data. Consider the following code:
var company = "Macromedia";
var product = "Flash";

// Set the variable sectionTitle
                   to "Macromedia Flash"
var sectionTitle = company + " " + product;
In lines 1 and 2, we store string values in variables. Then, we join those values together with a space. Two of our string values are contained in variables, one (the space) is a string literal. Not a problem. Happens all the time.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The Boolean Type
Boolean data is used to represent the logical states of truth and falsehood. There are, hence, only two legal values of the boolean datatype: true and false. Notice that there are no quotation marks around the words true and false because Boolean data is not string data. The keywords true and false are the reserved primitive data values and may not be used as variable names or identifiers.
We use Boolean values to add logic to the execution of code. For example, we might assign the value true to a variable that tracks the status of a spaceship's firepower:
shipHasDoubleShots = true;
By comparing shipHasDoubleShots to the Boolean literal true, we can then decide how much damage to inflict when a shot hits its target:
if (shipHasDoubleShots == true) {
  // Shoot them with twice the power.
  // This will be reached if the comparison is true.
} else {
  // Shoot them with a single dose.
  // This will be reached if the comparison is false.
}
When the double-shot power runs out, we can set the variable to false:
shipHasDoubleShots = false;
This will cause the larger expression shipHasDoubleShots == true to become false, causing the single-damage-dose script to execute when a shot hits its target.
All comparison operators express results with Boolean values. When we ask, "Is the user's guess the same as the password?" the answer is given as a Boolean:
// userGuess == password will yield either true or false
if (userGuess == password) {
  gotoAndStop("secretContent");
}
And when we ask, "Is the movie clip rotated greater than 90 degrees?" the answer, again, is a Boolean:
// myClip._rotation > 90 will yield either true or false
if (myClip._rotation > 90) {  
  // Fade out the clip if it's rotated past 90 degrees
  myClip._alpha = 50;
}
Many internal ActionScript properties and methods describe the Flash movie environment in Boolean terms. For example, if we ask, "Is the spacebar being pressed?" the interpreter answers with a Boolean:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Undefined
Most of the datatypes we've explored so far have been used for storing and manipulating information. The undefined datatype has a more narrow purpose: it is used to check whether a variable exists or whether a variable has yet been assigned a value. The undefined datatype has only one legal value, the primitive value undefined.
When we first define a variable, it is assigned the value undefined by default:
var velocity;
To the interpreter, the preceding statement reads:
var velocity = undefined;
To check whether a variable has a value, we can compare the variable to undefined, as in:
if (myVariable != undefined) {
  // myVariable has a value, so proceed as desired...
}
Note that an undefined value is converted to the empty string when used as a string. For example, if firstName is undefined, the following trace( ) statement will display "" (the empty string):
var firstName;
trace(firstName);  // Displays nothing (the empty string)
This same code in JavaScript would display the string "undefined" instead of the empty string. ActionScript converts undefined to "" for the sake of backward compatibility.
Because there was no undefined type in Flash 4 ActionScript, many Flash 4 programs used the empty string to check whether a variable had a useful value. Code like this was common:
if (myVar eq "") { 
  // Don't do anything yet: myVar is undefined 
}
If Flash 5 converted undefined to anything other than "" in a string context, old code like that would break in the Flash 5 player.
Note that ActionScript returns undefined both for variables that do not exist and variables that have been declared but have no value. This is also a departure from JavaScript, where references to variables that do not exist cause an error.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Null
Intellectually, the null type is nearly identical to the undefined type. Like the undefined datatype, the null datatype is used to represent a lack of data and has only one legal value, the primitive value null. The null value is not assigned by the interpreter automatically, but rather by us deliberately.
We assign null to a variable, array element, or object property to indicate that the specified data container does not contain a legal number, string, boolean, array, or object value.
Note that null only compares equal to itself and undefined:
null == undefined;   // true
null == null;        // true
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Onward!
We've learned a lot more so far than you may have realized. We've built a solid foundation that will allow us to understand the advanced topics coming in later chapters. If you haven't mastered all the details yet, don't worry. Your training will come back to you when you need it. Keep the faith during the next chapter in which you'll learn how to merge and transform data. Following that we'll get into some more fully formed applied examples.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 5: Operators
An operator is a symbol or keyword that manipulates, combines, or transforms data. If you're new to programming, you'll notice that some mathematical operators, like + (addition) and - (subtraction) are very familiar. In other cases, you'll have to learn special programming syntax even if the concepts are familiar. For example, to multiply two numbers, ActionScript uses the symbol * (the multiplication operator) instead of the X typically taught in grade school. For example, this multiplies 5 times 6:
5 * 6;
Though each operator has its own specialized task, all operators share a number of general characteristics. Before we consider the operators individually, let's see how they behave generally.
Operators perform some action using the data values (operands ) supplied. For example, in the operation 5 * 6, the numbers 5 and 6 are the operands of the multiplication operator (*). The operands can be any kind of expression, for example:
player1score + bonusScore;              // Operands are variables
(x + y) - (Math.PI * radius * radius);  // Operands are complex expressions
Observe in the second example that both the left and right operands of the - operator are expressions that themselves involve other operations. We can use complex expressions to create even larger expressions, such as:
((x + y) - (Math.PI * radius * radius)) / 2  // Divide the whole thing by 2
When expressions become very large, consider using variables to hold interim results for both convenience and clarity. Remember to name your variables descriptively, such as:
var radius = 10;
var height = 25;
var circleArea = (Math.PI * radius * radius);
var cylinderVolume = circleArea * height;
Operators are sometimes categorized according to how many operands they take. Some ActionScript operators take one operand, some take two, and one even takes three:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
General Features of Operators
Though each operator has its own specialized task, all operators share a number of general characteristics. Before we consider the operators individually, let's see how they behave generally.
Operators perform some action using the data values (operands ) supplied. For example, in the operation 5 * 6, the numbers 5 and 6 are the operands of the multiplication operator (*). The operands can be any kind of expression, for example:
player1score + bonusScore;              // Operands are variables
(x + y) - (Math.PI * radius * radius);  // Operands are complex expressions
Observe in the second example that both the left and right operands of the - operator are expressions that themselves involve other operations. We can use complex expressions to create even larger expressions, such as:
((x + y) - (Math.PI * radius * radius)) / 2  // Divide the whole thing by 2
When expressions become very large, consider using variables to hold interim results for both convenience and clarity. Remember to name your variables descriptively, such as:
var radius = 10;
var height = 25;
var circleArea = (Math.PI * radius * radius);
var cylinderVolume = circleArea * height;
Operators are sometimes categorized according to how many operands they take. Some ActionScript operators take one operand, some take two, and one even takes three:
-x                                         // One operand
x * y                                      // Two operands
(x == y) ? "true result" : "false result"  // Three operands
Single-operand operators are called unary operators; operators with two operands are called binary operators; operators with three operands are called ternary operators. For our purposes, we'll look at operators according to what they do, not the number of operands they take.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The Assignment Operator
We've already used the assignment operator frequently. It can place a value into a variable, array element, or object property. Assignment operations take the form:
               identifier = expression
            
The identifier is the variable, array element, or object property into which we want to place our value. The expression represents the value (i.e., data) that we want to store. For example:
x = 4;                  // Assign 4 to the variable x
x = y;                  // Assign the value of y to the variable x
name = "dj duong";      // Assign a string to the variable name
products[3] = "Flash";  // Assign a string to the 4th element of products

// Assign a number to the area property of square
square.area = square.width * 2;
We may also perform multiple assignment operations at once, like this:
x = y = 4;  // Set both x and y to 4
Remember that assignment operations have right-to-left associativity, so 4 is assigned first to y then the value of y (which is now 4) is assigned to x.
Assignment operations are often used to set a variable's new value based in part on its old value. For example:
counter = counter + 10;             // Add 10 to the current value of counter
xPosition = xPosition + xVelocity;  // Add xVelocity to xPosition
score = score / 2;                  // Divide score by two
ActionScript supports a shorthand version of assignment, called compound assignment that combines operators such as +, -, / with the assignment operator to form a single "calculate-while-assigning" operation. So, to combine addition with assignment we use +=. To combine division with assignment, we use /=. The previous examples, hence, can be written more succinctly with compound assignment operators as follows:
counter += 10;
xPosition += xVelocity;
score /= 2;
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Arithmetic Operators
The arithmetic operators perform mathematical operations on numeric operands. If you use non-numeric operands with the arithmetic operators, ActionScript will attempt to convert the foreign data to a number. For example, false - true evaluates to -1 because false converts to the numeric value and true converts to 1. Similarly, the expression "3" * "5" results in the number 15, because the strings "3" and "5" are converted to the numbers 3 and 5 before the multiplication is performed. The + operator, however, presents a special case: when used with at least one string operand, it performs a string concatenation operation, not mathematical addition.
If an attempt to convert a non-numeric operand to a number fails, the operand will be set to the special numeric value NaN. This results in the entire operation yielding NaN. Refer to Table 3.1 for details on numeric conversion.
The addition operator returns the sum of its two operands:
                  operand1 + operand2
               
In order to return a meaningful mathematical result, the operands of + should be expressions that yield a numeric value, such as:
234 + 5          // Returns 239
(2 * 3 * 4) + 5  // Returns 29
The addition operator is unique among the arithmetic operators in that if one or both of its operands are strings, it performs as a string concatenation. Refer to Section 4.6.1 in Chapter 4.
A handy variation on addition, the increment operator accepts a single operand and simply adds 1 to its current value. Increment has two general forms, called prefix increment and postfix increment, as follows:
++operand    // Prefix increment
operand++    // Postfix increment
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The Equality and Inequality Operators
We use the equality operator (==) to test whether two expressions have the same value. The equality test takes the general form:
               operand1 == operand2
            
where operand1 and operand2 may be any valid expression. The equality operator can compare operands of any type. When operand1 and operand2 are equal, the expression returns the Boolean value true; when they differ, it returns the Boolean value false. For example:
var x = 2;
x == 1     // false
x == 2     // true
The equality operator is created using two equal signs in a row (==). It determines whether two expressions are equal and should not be confused with the assignment operator (=) which is used to assign a variable a new value.
Consider this example:
if (x = 5) {
  trace ("x is equal to 5")
}
The preceding example does not check whether x equals 5. Instead, it sets x equal to 5. The proper expression is as follows:
// Use == instead of =
if (x == 5) {  
  trace ("x is equal to 5")
}
For the primitive datatypes, the result of most equality tests is fairly intuitive. Table 5.2 lists the rules that govern equality for each primitive datatype.
Table 5.2: Equality of Primitive Datatypes
Type
Terms of Equality (both operands must be of given type)
Number
If operand1 is the same number as operand2, the result is true. If both operands are +Infinity or both are
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The Comparison Operators
The comparison operators (also called relational operators) are used to determine which of two values appears first in a given order. Like the equality and inequality operators, the comparison operators return one of the Boolean values true or false indicating whether the relationship described in the comparison is accurate (true) or inaccurate (false).
Comparison operators work only with strings and numbers. When the two operands of a comparison operator are numbers, the comparison is performed mathematically: 5 < 10 is true, -3 < -6 is false, and so on. When the two operands of a comparison operator are strings, the comparison is performed according to character code points, as shown in Appendix B. See Section 4.6.2 in Chapter 4 for details on string comparisons.
The interpreter will attempt to convert any nonstring or nonnumeric data value used in a comparison operation to the string or number type. We'll consider the effect of datatype conversions on comparison operations after we discuss the comparison operators themselves.
The less-than operator takes the general form:
                  operand1
                   < 
                  operand2
               
If the operands are numeric, the less-than operator returns the Boolean true if operand1 is mathematically smaller than operand2:
5 < 6        // true
5 < 5        // false; they are equal, but 5 is not less than 5
-3 < -6      // false; -3 is larger than -6
-6 < -3      // true;  -6 is smaller than -3
If the operands are strings, the less-than operator returns true if operand1 comes "alphabetically" before operand2 (see Appendix B); otherwise, returns false:
"a" < "z"         // true; lowercase "a" comes before lowercase "z"
"A" < "a"         // true; uppercase letters come before lowercase
"Z" < "a"         // true; uppercase letters come before lowercase
"hello" < "hi"    // true; "e" is less than "i"
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The String Operators
Special string operators—concatenation (&), equality (eq ), inequality (ne), and comparison (lt, gt, le, ge)—were required when using string data in Flash 4. In Flash 5 and later, the special string operators are deprecated (i.e., supported but obsolete). Use ==, !=, <, >, <=, and >= for string comparisons, unless exporting to Flash 4 .swf format, in which case you must use the old operators (eq , ne, lt, gt, le, ge). Use + for string concatenation, unless exporting to Flash 4 format, in which case you should use add instead of & (because & is the bitwise AND operator in Flash 5 and later).
For more details and a list of Flash 4 versus Flash 5 string-operation equivalencies, see Section 4.6 and Table 4.2 in Chapter 4.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The Logical Operators
In Chapter 4, we learned how to make logical decisions using Boolean values. The decisions we considered were based on single factors: if a movie hasn't loaded, don't start playing; if a spaceship has double-shot power, increase the damage its shots inflict, and so on. Not all programming logic is so simple. We'll often want to consider multiple factors in our branching (i.e., decision-making) logic.
Suppose, for example, that we are making a personalized Flash site that requires users to log in. If a user logs in as a guest, the content he can see is limited. When a registered user logs into the site, we set a variable that indicates, for the duration of our movie, that the user is allowed to see privileged content:
var userStatus = "registered";
To decide whether to allow access to a restricted area, we use a Boolean check like this:
if (userStatus == "registered") {
  // It's okay, let 'em in...
}
Suppose we want to demonstrate the site to prospective investors without forcing them to register and without showing them material reserved for registered users. We can invent a new user category, "specialGuest," that allows investors to see more than a guest but not as much as a registered user. When we want to identify someone as a special guest, we set userStatus to "specialGuest."
How do we perform a Boolean check now that there are two categories of users to allow in? We could do things the brutish, painful way by duplicating portions of our code:
if (userStatus == "registered") {
  // Execute legal-user code...
}

if (userStatus == "specialGuest") {
  // Execute exact same legal-user code...
}
Obviously, that's going to turn into a real headache to maintain. Every bit of complexity we add to our script doubles, and we end up with serious version-control problems.
We'd prefer to perform a single Boolean check that says, "If the user is registered or if the user is a special guest, then grant access." We can produce compound logical phrases like that with Boolean
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The Grouping Operator
Aside from being used in function calls, parentheses ( ) can also be used to group a phrase of code to override the precedence of various operators. Parentheses are also required in some statements, most notably if statements. Parentheses take the general form:
(expression)
The expression within the parentheses is evaluated and returned. Here are some examples:
if (x == y) {                 // Syntactically required for if statement
  trace("x and y are equal"); // Required for the function call
}
(5 + 6) * 7                   // Force a nonstandard order of operation
(x >= 100) || (y <= 50)       // Parentheses not required but added for legibility
x >= 100 || y <= 50           // No parentheses...a little harder to read
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The Comma Operator
Rarely used, the comma, operator ( ,) allows us to evaluate two expressions where a single expression is expected. It takes the general form:
               operand1, operand2
            
Both operands must be legal expressions. When a comma operation executes, operand1 is evaluated, then operand2 is evaluated, and then the resolved value of operand2 is returned. In practice, the return value of the comma operator is usually ignored.
The comma operator is primarily used in for loops that initialize multiple variables as shown in Example 5.6. Note that in the first line of the example, the expressions i=0 and j=10 are both operands of the comma operator. (These expressions cause i and j to be initialized to and 10.) The expressions i++ and j-- are both operands of a second comma operator. (These expressions cause i to be incremented and j to be decremented each time the loop executes.) The comma operator is used in order to squeeze multiple expressions within the confines of the for loop's syntax.
Example 5.6. Using the Comma Operator in a for Loop
for (var i=0, j=10; i!=j; i++, j--) {
  trace ("i: " + i + " j: " + j);
}

// Which produces this output...
 i: 0 j: 10
 i: 1 j: 9
 i: 2 j: 8
 i: 3 j: 7
 i: 4 j: 6
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The void Operator
The void operator is used to evaluate an expression without returning a value. It has the syntax:
void expression
            
where expression is the expression to evaluate. In JavaScript, void is used to evaluate a JavaScript expression in a hypertext link without causing the result to appear in the browser's address bar. There are few, if any, such applications for void in ActionScript; it is included for the sake of compatibility with ECMA-262.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Other Operators
The remaining operators apply to topics considered in other chapters. We'll include them here for quick reference only and describe their usage fully in those chapters.
If you're planning to develop large-scale systems in which every iota of memory, calculation speed, and transfer-rate optimization makes a meaningful difference in performance, read about the bitwise operators in Chapter 15. Otherwise, use the Boolean logical operators, which perform the same tasks the bitwise operators do, albeit in a less optimized way.
The typeof operator is used to determine the datatype of an expression. It takes one operand, as follows:
typeof operand;
where operand may be any legal expression. The return value of the typeof operation is a string indicating the datatype of the evaluated operand. See Chapter 3 for more details.
The new operator creates a new composite datum — either an array or an object. The object may be a member of a built-in class or a user-defined class. The syntax for new is:
new constructor
               
where constructor must be a function that defines the properties of the newly created object. See Chapter 11, and Chapter 12.
We use the delete operator to remove an object, an object property, an array element, or variables from a script. The syntax for delete is:
delete identifier  
               
If identifier is not a data container (variable, property, or element), the delete operation fails and returns the value false; otherwise, it returns true, indicating success. See Chapter 11.
As we'll see in Chapter 11 and Chapter 12, we use the [ ] operator to retrieve and set the value of an array element or an object property. When accessing an array it takes the form:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Onward!
Like all languages, ActionScript has a grammar and different parts of speech. Over the last few chapters, you've learned the equivalent of sentence structure, nouns, adjectives, and conjunctions. Now, let's move on to statements, which, like verbs, can do things. Statements complete our ability to form sentence-like instructions.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 6: Statements
We saw in earlier chapters how ActionScript stores and manipulates data. In this chapter we'll learn how to do things with that data. We'll give Flash instructions in the form of statements, or phrases of code that instruct the interpreter to perform some task.
To make something happen in Flash—whether stopping a sound, playing a movie, running a function, or looping some code—we use a statement. In fact, an ActionScript program can be defined as nothing more than a list of statements that tell the interpreter what we want Flash to do. Here, for example, is an entire ActionScript program, which consists of four statements and tells the interpreter to load a web page into the browser:
var protocol = "http";                                   // Statement 1
var domain = "www.moock.org";                            // Statement 2
var path = "webdesign/flash/";                           // Statement 3
getURL(protocol + "://" + domain + "/" + path);          // Statement 4
Scripting a movie with ActionScript is simply a matter of attaching statements to frames, movie clips, and buttons. This chapter explores the syntactic makeup of statements and lists the general statement categories. We'll touch on all the ActionScript statements in this chapter, but some of the more important ones will be examined in detail in later chapters.
Conceptually speaking, there are five core types of statements:
Statements that control the execution flow of a program
loops
conditionals
ifFrameLoaded
Statements that declare variables
var
set
Statements that declare, call, and return values from functions
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Types of Statements
Conceptually speaking, there are five core types of statements:
Statements that control the execution flow of a program
loops
conditionals
ifFrameLoaded
Statements that declare variables
var
set
Statements that declare, call, and return values from functions
function
function call
call
return
Statements that deal with objects
with
for . . . in
Statements that represent a data value
any expression (especially expressions with side effects)
These informal categories help us to understand what we can tell the interpreter to do using statements. At first glance, the list may seem fairly limited. However, we'll see that there are many variations of conditionals and loops and that there are thousands of things we can do via function calls. First, let's see how statements are formed.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Statement Syntax
Statements are typically made up of keywords and expressions . We've already seen the var statement, which declares and optionally initializes a variable. Here's an example of the var statement's general syntax:
var numFrames;
The keyword (var in this case) identifies the beginning of the statement. Then comes the syntax required by the statement, which, in our example, is simply the name of a variable, numFrames. Finally, a semicolon marks the end of the statement.
In ActionScript, every statement should end with a semicolon. (It's good form to use semicolons, but not officially mandatory. In Chapter 14, I'll have more to say about semicolon usage.)
Some statements can take multiple forms. For example, we can use var with or without an optional initial assignment (in this case 10 is a simple expression whose value is assigned to x):
var x;       // Simple declaration
var x = 10;  // Declaration with assignment
We'll learn the specific syntax of each statement throughout the rest of this chapter.
Some statements actually include other statements, or substatements, as part of their syntax. For example, the if statement has this syntax:
if (expression) substatement;
The substatement, which is executed only if expression evaluates to true, can be a single statement such as a variable declaration statement:
if (x == 5) var numFrames = 2;
or it can be a series of statements grouped together as a statement block :
if (x == 5) {
  var numFrames;
  numFrames = 10;
  play( );
}
As you can see, a statement block is any number of statements on one or more lines surrounded by curly braces:
{ statement1; statement2; statement3... }
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The ActionScript Statements
Now that you know how a typical statement is formed, skim Table 6.1 to acquaint yourself with some of the things that ActionScript statements do.
Table 6.1: The ActionScript Statements
Statement
Syntax
Use
break
break;
Cancels a loop
call
call (frame);
Executes the script on a remote frame
continue
continue;
Restarts the current loop
do-while
do {
   statements
} while (expression);
A variation of a while loop
empty statement
;
Holds a place where a statement is expected, and used with evaluate in novice mode
for
for (init; test; increment) {
   statements
}
Executes some code repetitively (a for loop)
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Statements Versus Actions
If you look through the Flash ActionScript editing environment, you won't find any reference to the word "statement." Even Macromedia's Flash 5 ActionScript Reference Guide uses the terms "Action" and "statement" interchangeably.
Using the term "Action" as a synonym for "statement" blurs the distinction between several different ActionScript tools. To see how, open the ActionScript editor and look in the Actions folder, as shown in Figure 1.2. Under the list of Actions in that folder, you'll find the statements we saw earlier in Table 6.1. Interspersed with the statements you'll also notice quite a few functions: gotoAndPlay( ), getURL( ), startDrag( ), and so on. Although the functions listed as Actions can be used in statements, they're technically not unique statement types—they're just built-in functions. Statements, some built-in functions, and event handlers are all called Actions by Macromedia. Throughout this book, we do not use the generic term Action. Instead, each Action is described with the term that matches its formal role in the language: either statement, function, or event handler.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Onward!
Though we've learned a lot about statements, two important statement types—conditionals and loops—are yet to come. We'll deal with those kinds of statements in the next two chapters.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 7: Conditionals
Most of the code examples we've seen so far have been very linear —each statement is executed in turn, starting with the first and ending with the last. Linear code always does the same thing. A conditional, by contrast, is a type of statement that performs an action only when a specified condition is met. In linear code, the interpreter might execute statement A, then statement B, then statement C. With conditional statements we can tell the interpreter to execute statement A, then execute either statement B or statement C, depending on condition X.
We can use conditionals to create and control situations that have more than one potential outcome. For example, suppose we want to create a password-protected site. When users attempt to log in, either the password is correct and the user is allowed to enter the site, or the password is wrong and the user sees an error message. The two outcomes require two very different blocks of code in our movie's script. One block needs to send the Flash playhead to a frame containing the site's welcome screen, and the other block needs to send the playhead to a frame with an error message. But only one of the blocks should be executed when the user attempts to log in. A conditional statement allows us to execute the appropriate block and skip the inappropriate one.
How does the interpreter know which code block to execute? When we define a conditional statement, we specify the condition that must be met in order for the first block of code to be executed. If the condition is not met, an alternate block of code may be executed (and that alternate block may, in turn, have its own condition). Essentially, we set up flowchart-like logic in our program that, in pseudocode, reads like this:
if (the first condition is met) {
  // Execute this code
} else if (the second condition is met) {
  // Execute this code
} ...otherwise {
  // Execute this code
}
Of course, we must describe each condition in terms the interpreter understands. Not a problem—that's just a question of syntax, which we'll learn next. Conceptually, all conditionals either allow or suppress the execution of a code block based on the specified condition. Now let's see how conditionals work in practice.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The if Statement
The if statement is your everyday, all-purpose conditional. We use if to create a two-pronged branch in our code, like a fork in the road. The if statement contains one or more substatements that are executed only when the specified condition is met. The if statement has the following syntax:
if (condition) {
  substatements
}
An if statement starts, not surprisingly, with the keyword if. The condition that must be satisfied for substatements to be executed is enclosed in parentheses. The substatements are one or more ActionScript statements. Each substatement should be on its own line and terminated with a semicolon. The entire if statement ends with a closing curly brace, (}), without a trailing semicolon.
The condition of our if statement can be any valid expression. When an if statement is executed, the interpreter checks the value of that expression (called the test expression). If it is true, the substatements are executed. Otherwise, the substatements are not executed. Here we use simple Boolean values as the test expression:
if (true) {          
  trace("The condition was met!");  // This statement will be executed
}
if (false) {         
  trace("The condition was met!");  // This statement is never executed
}
Of course, there's no practical reason to use Boolean literals as test expressions because their values never change. Instead, we'll use complex expressions that return Boolean values. For example, expressions that involve a comparison operation return a Boolean value, which makes them perfect for conditional test expressions:
var pointerX = _xmouse;  // Horizontal location of the mouse

// If pointerX > 300 yields true...
if (pointerX > 300) {
  // ...this statement is executed
  trace("The mouse is past the 300 pixel mark");  
}
Now for the cool part: the test expression of a conditional doesn't necessarily have to evaluate to a Boolean—any expression will do. We can use a string or a number as the test expression of a conditional:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The else Statement
With a lone if statement, we can cause a single code block to be optionally executed. By adding an else clause, we can choose which of two code blocks should be executed. Syntactically, an else statement is an extension of an if statement:
if (condition) {
  substatements1
} else {
  substatements2
}
where condition may be any valid expression. substatements1 will be executed if condition is true; substatements2 will be executed if condition is false. In other words, an else statement is perfect for depicting a mutually exclusive decision; one code block will be executed and the other will not.
Some code to demonstrate:
var lastName = "Grossman";
var gender = "male";
if (gender == "male") {
  trace("Good morning, Mr. " + lastName + ".");
} else {
  trace("Good morning, Ms. " + lastName + ".");
}
The else clause often acts as the backup plan of an if statement. Recall our password-protected web site example. If the password is correct, we let the user enter the site; otherwise, we display an error message. Here's some code we could use to perform the password check (assume that userName and password are the user's entries and that validUser and correctPassword are the correct login values):
if (userName == validUser && password == correctPassword) {
  gotoAndPlay("intro");
} else {
  gotoAndStop("loginError");
}
Simple two-part conditional statements can be expressed conveniently with the conditional operator (?:). The conditional operator has three operands, which you'll recognize as analogous to the components of an if-else statement series:
                  condition ? expression1 : expression2;
In a conditional operation, if condition is true, expression1 is evaluated and returned. Otherwise, expression2 is evaluated and returned. The conditional operator is just a quicker way to write the following conditional statement:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The else if Statement
Using if and else, we can optionally execute one of two code blocks. By using if and else if, we can optionally execute one (or even none) of an unlimited number of code blocks. Like else, else if is a syntactic extension of an if statement:
if (condition1) {
  substatements1
} else if (condition2) {
  substatements2
} else if (condition3) {
  substatements3
} else {
  substatements4  // Catchall if other conditions were not met
}
where condition1, condition2, and condition3 must be valid expressions. substatements1 will be executed if condition1 is true. If condition1 is false, substatements2 will be executed if condition2 is true. Otherwise, condition3 is evaluated and so on for as many else if statements are provided. If none of the test expressions are true, the statements in the final catchall else clause will be executed. For example, we could write a login-checking routine to provide insightful error messages, like this:
if (userName != validUser) {
  message = "User not found. Please try again.";
  gotoAndStop("loginError");
} else if (password != correctPassword) {
  message = "Password incorrect. Please try again.";
  gotoAndStop("loginError");
} else {
  gotoAndPlay("intro");
}
Note that an else if statement is merely a combination of an else with a nested if statement. Although the following two code segments are equivalent, the first one is much easier to read:
// Normal "else if" syntax
if (x > y) {
  trace("x is larger than y");
} else if (x < y) {
  trace("x is smaller than y");
} else {
  trace("x and y are equal");
}

// Expanded if/else chain
if (x > y) {
  trace("x is larger than y");
} else {
  if (x < y) {
    trace("x is smaller than y");
  } else {
    trace("x and y are equal");
  }
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Simulating the switch Statement
Though switch statements (sometimes called case statements) are not supported by ActionScript, this common form of complex conditional can be emulated. A switch statement lets us execute only one of a series of possible code blocks based on the value of a single test expression. For example, in the following JavaScript switch statement, we greet the user with a custom message depending on the value of the test expression gender:
var surname = "Porter";
var gender = "male";

switch (gender) {   
  case "femaleMarried" :       
    alert("Hello Mrs. " + surname);       
    break;    
  case "femaleGeneric" :      
    alert("Hello Ms. " + surname);  
    break;   
  case "male" :       
    alert("Hello Mr. " + surname);      
    break;    
  default :      
    alert("Hello " + surname); 
}
In the JavaScript example, switch attempts to match the value of gender to one of the case expressions: "femaleMarried", "femaleGeneric", or "male". Because gender matches the expression "male", the substatement alert("Hello Mr. " + surname); is executed. If the test expression had not matched any case, then the default statement—alert("Hello " + surname);—would have been executed.
In ActionScript, we can simulate a switch statement using a chain of if-else if-else statements, like this:
var surname = "Porter";
var gender = "male";

if (gender == "femaleMarried") {
  trace("Hello Mrs. " + surname);
} else if (gender == "femaleGeneric") {
  trace("Hello Ms. " + surname);
} else if (gender == "male") {
  trace("Hello Mr. " + surname);
} else {
  trace("Hello " + surname);
}
In a more advanced approach, we could simulate a switch as a series of functions stored in the properties of a generic object. Example 7.1 shows the technique. Pay close attention to the comments to learn how it works. Also note the use of the conditional operator, which we encountered earlier.
Example 7.1. A Simulated switch Statement
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Compact Conditional Syntax
Throughout this book we use statement blocks (statements surrounded by curly braces) with all conditional statements, even if a block contains only one statement:
if (x == y) {
  trace("x and y are equal");
}
For the sake of terseness, ActionScript does not require curly braces when a conditional has only one substatement. A single substatement may quite legitimately be placed directly after an if or an else if statement without any curly braces, like this:
if (x == y) trace ("x and y are equal");
Or like this:
if (x == y)
  trace ("x and y are equal");
For some programmers, this style can be a little slower to read and slightly more error prone, though it undeniably saves room in source code.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Onward!
Conditional statements are an immensely important component of ActionScript. They give us precise control over the execution of our code. In the next chapter, we'll examine another kind of important execution-control statement, loops.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 8: Loop Statements
In the previous chapter, we learned that a conditional causes a statement block to be executed once if the value of its test expression is true. A loop, on the other hand, causes a statement block to be executed repeatedly, for as long as its test expression remains true.
Loops come in a variety of tasty flavors: while, do-while, for, and for-in. The first three types have very similar effects, but with varying syntax. The last type of loop, for-in, is a specialized kind of loop used with objects. We'll start our exploration of loops with the while statement, the easiest kind of loop to understand.
Structurally, a while statement is constructed much like an if statement: a main statement encloses a block of substatements that are executed only when a given condition is true:
while (condition) {
  substatements
}
If the condition is true, substatements are executed. But unlike the if statement, when the last substatement is finished, execution begins anew at the beginning of the while statement (that is the interpreter "loops" back to the beginning of the while statement). The second pass through the while statement works just like the first: the condition is evaluated, and if it is still true, substatements are executed again. This process continues until condition becomes false, at which point execution continues with any statements that follow the while statement in the script.
Here's an example of a very simple loop:
var i = 3;
while (i < 5) {
  trace("x is less than 5");
}
The example reliably represents the correct syntax of a while loop but is most likely in error. To see why, let's follow along with the interpreter as it executes the example.
We start with the statement before the while statement, var i = 3, which sets the variable i to 3. Because the variable i is used in the test expression of the loop, this step is often called the loop initialization
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The while Loop
Structurally, a while statement is constructed much like an if statement: a main statement encloses a block of substatements that are executed only when a given condition is true:
while (condition) {
  substatements
}
If the condition is true, substatements are executed. But unlike the if statement, when the last substatement is finished, execution begins anew at the beginning of the while statement (that is the interpreter "loops" back to the beginning of the while statement). The second pass through the while statement works just like the first: the condition is evaluated, and if it is still true, substatements are executed again. This process continues until condition becomes false, at which point execution continues with any statements that follow the while statement in the script.
Here's an example of a very simple loop:
var i = 3;
while (i < 5) {
  trace("x is less than 5");
}
The example reliably represents the correct syntax of a while loop but is most likely in error. To see why, let's follow along with the interpreter as it executes the example.
We start with the statement before the while statement, var i = 3, which sets the variable i to 3. Because the variable i is used in the test expression of the loop, this step is often called the loop initialization. Next, we begin executing the while statement by resolving the test expression: i < 5. Because i is 3, and 3 is less than 5, the value of the test expression is true so we execute the trace( ) statement in the loop.
With that done, it's time to restart the loop. Once again, we check the value of the test expression. The value of the variable i has not changed, so the test expression is still true and we execute the trace( ) statement again. At this point, we're done executing the loop body, so it's time to restart the loop. Guess what? The variable i still has not changed, so the test expression is still true and we must execute the
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Loop Terminology
In the previous section we encountered several new terms. Let's look at these more formally, so that you'll understand them well when working with loops:
Initialization
The statement or expression that defines one or more variables used in the test expression of a loop.
Test expression
The condition that must be met in order for the substatements in the loop body to be executed. Often called a condition or test, or sometimes, control.
Update
The statements that modify the variables used in the test expression before a subsequent test. A typical update statement increments or decrements the loop's counter.
Iteration
One complete execution of the test expression and statements in the loop body. Sometimes referred to as one loop or one pass.
Nesting or nested loop
A loop that contains another loop so that you can iterate through some sort of two-dimensional data. For example, you might loop through each row in a column for all the columns in a table. The outer or top-level loop would progress through the columns, and the inner loop would progress through the rows in each column.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The do-while Loop
As we saw earlier, a while statement allows the interpreter to execute a block of code repeatedly while a specified condition remains true. Due to a while loop's structure, its body will be skipped entirely if the loop's condition is not met the first time it is tested. A do-while statement lets us guarantee that a loop body will be executed at least once with minimal fuss. The body of a do-while loop always executes the first time through the loop. The do-while statement's syntax is somewhat like an inverted while statement:
do {
  substatements
} while (condition);
The keyword do begins the loop, followed by the substatements of the body. On the interpreter's first pass through the do-while statement, substatements are executed before condition is ever checked. At the end of the substatements block, if condition is true, the loop is begun anew and substatements are executed again. The loop executes repeatedly until condition is false, at which point the do-while statement ends. Note that a semicolon is required following the parentheses that contain the condition.
Obviously, do-while is handy when we want to perform a task at least once and perhaps subsequent times. In Example 8.2 we duplicate a series of twinkling-star movie clips from a clip called starParent and place them randomly on the Stage. Our galaxy will always contain at least one star, even if numStars is set to 0.
Example 8.2. Using a do-while Loop
var numStars = 5;
var i = 1;
do {
  // Duplicate the starParent clip
  duplicateMovieClip(starParent, "star" + i, i);

  // Place the duplicated clip randomly on Stage
  _root["star" + i]._x = Math.floor(Math.random( ) * 551);
  _root["star" + i]._y = Math.floor(Math.random( ) * 401);
} while (i++ < numStars);
Did you notice that we sneakily updated the variable i in the test expression? Remember from Chapter 5, that the post-increment operator both returns the value of its operand and also adds one to that operand. The increment operator is very convenient (and common) when working with loops.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The for Loop
A for loop is essentially synonymous with a while loop but is written with more compact syntax. Most notably, the loop header can contain both initialization and update statements in addition to the test expression.
Here's the syntax of the for loop:
for (initialization; condition; update) {
  substatements
}
The for loop places the key components of a loop tidily in the loop header, separated by semicolons. Before the first iteration of a for loop, the initialization statement is performed (once and only once). It is typically used to set the initial value of an iterator variable. As with other loops, if condition is true, substatements are executed. Otherwise, the loop ends. At the end of each loop iteration, the update statement is executed, before condition is tested again to see if the loop should continue. Here's a typical for loop that simply counts from 1 to 10:
for (var i = 1; i <= 10; i++) {
  trace("Now serving number " + i);
}
It's easier to understand how a for loop works when you see its equivalent constructed using the while loop syntax:
var i = 1;
while (i <= 10) {
  trace("Now serving number " + i);
  i++;
}
Once you're used to the for syntax, you'll find it saves space and allows for easy scanning of the loop's body and controls.
If we want to control more than one factor in a loop, we may optionally use more than one iterator variable. A while loop with multiple iterators may look like this:
var i = 1;
var j = 10;
while (i <= 10) {
  trace("Going up " + i);
  trace("Going down " + j);
  i++;
  j--;
}
The same effect can be achieved in a for statement using the comma operator:
for (var i = 1, j = 10; i <= 10; i++, j--) {
  trace("Going up " + i);
  trace("Going down " + j);
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The for-in Loop
A for-in statement is a specialized loop used to list the properties of an object. New programmers may want to skip this section for now and return to it after reading Chapter 12.
Rather than repeating a series of statements until a given test expression yields the value false, a for-in loop iterates once for each property in the specified object. Therefore, for-in statements do not need an explicit update statement because the number of loop iterations is determined by the number of properties in the object being inspected. The syntax of a for-in loop looks like this:
for (var thisProp in object) {
  substatements;  // Statements typically use thisProp in some way
}
The substatements are executed once for each property of object; object is the name of any valid object; thisProp is any variable name or identifier name. During each loop iteration, the thisProp variable temporarily holds a string that is the name of the object property currently being enumerated. That string value can be used during each iteration to access and manipulate the current property. The simplest example of a for-in loop is a script that lists the properties of an object. Here we create an object and then itemize its properties with a for-in loop:
var ball = new Object( );
ball.radius = 12;
ball.color = "red";
ball.style = "beach";

for (var prop in ball) {
  trace("ball has the property " + prop);
}
Because prop stores the names of the properties of ball as strings, we can use prop with the [] operator to retrieve the values of those properties, like this:
for (var prop in ball) {
  trace("ball." + prop + " is " + ball[prop]);
}
Retrieving property values with a for-in loop also provides a super way to detect the movie clips present on a timeline. For a demonstration of the for-in loop used as a movie clip detector, see Example 3.1.
Note that the properties of the object being inspected in a for-in loop are not enumerated in any predictable order. Also,
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Stopping a Loop Prematurely
In a simple loop, the test expression is the sole factor that determines when the loop stops. When the test expression of a simple loop yields false, the loop terminates. However, as loops become more complex, we may need to arbitrarily terminate a running loop regardless of the value of the test expression. To do so, we use the break and continue statements.
The break statement ends execution of the current loop. It has the modest syntax:
break
The only requirement is that break must appear within the body of a loop.
The break statement provides a way to halt a process that is no longer worth completing. For example, we might use a for-in loop to build a form-checking routine that cycles through the input-text variables on a timeline. If a blank input field is found, we alert the user that she hasn't filled in the form properly. We can abort the process by executing a break statement. Example 8.3 shows the code. Note that the example assumes the existence of a movie clip called form that contains a series of declared input variables named input01, input02, and so on.
Example 8.3. A Simple Form-Field Validator
for (var prop in form) {
  // If this property is one of our "input" text fields
  if (prop.indexOf("input") != -1) {
    // If the form entry is blank, abort the operation
    if (form[prop] == "") {
      displayMessage = "Please complete the entire form.";
      break;
    }
    // Any substatements following the break command are not reached
    // when the break is executed
  }
}
// Execution resumes here after the loop terminates whether
// due to the break command or the test condition becoming false
You can use the break statement to interrupt a loop that would otherwise be infinite. This allows you to perform, say, the statements in the first half of the code block without necessarily executing the statements following an
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Timeline and Clip Event Loops
All the loops we've looked at so far cause the interpreter to repeatedly execute blocks of code. Most of your loops will be of this "ActionScript-statement" type. But it's also sometimes desirable to create a timeline loop by looping Flash's playhead in the timeline. To do so, attach a series of statements to any frame; on the next frame, attach a gotoAndPlay( ) function whose destination is the previous frame. When the movie plays, the playhead will cycle between the two frames, causing the code on the first frame to be executed repeatedly.
We can make a simple timeline loop by following these steps:
  1. Start a new Flash movie.
  2. On frame 1, attach the following statement:
    trace("Hi there! Welcome to frame 1");
  3. On frame 2, attach the following statements:
    trace("This is frame 2");
    gotoAndPlay(1);
  4. Select Control → Test Movie.
When we test our movie, we see an endless stream of the following text:
Hi there! Welcome to frame 1
This is frame 2
Hi there! Welcome to frame 1
This is frame 2
Timeline loops can do two things ordinary loops cannot:
  • They can execute a block of code an infinite number of times without causing an error.
  • They can execute a block of code that requires a Stage update between loop iterations.
This second feature of timeline loops requires a little more explanation. When any frame's script is executed, the movie Stage is not updated visually until the end of the script. This means that traditional loop statements cannot be used to perform repetitive visual or audio tasks because the task results aren't rendered between each loop iteration. Repositioning a movie clip, for example, requires a Stage update, so we can't programmatically animate a movie clip with a normal loop statement.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Onward!
Well, we've come pretty far. The end of this chapter marks a milestone—it ends our examination of the ActionScript statements. That means we have variables, data, datatypes, expressions, operators, and statements under our belt. These components of the language are the foundation of all scripts. If you've read and understood everything up to this point, or at least most of it, you can officially claim that you're able to "speak" ActionScript.
In the remainder of Part I, we'll work on making our conversations more eloquent and our commands more powerful. We'll consider the advanced topics of how to make code portable, how to create events that initiate the execution of our code, how to manage complex data, and how to manipulate movie clips programmatically. These techniques will help us build more advanced applied examples.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 9: Functions
I'm almost giddy to tell you about functions because they're such a powerful part of ActionScript. A function is simply a chunk of code that can be reused throughout a program. Not only do functions lend enormous flexibility and convenience to our scripts, they also give us control over Flash movie elements. I can hardly imagine programming without functions—they ease everything from sorting words to calculating the distance between two movie clips. We'll introduce functions in this chapter before learning how to create complex, powerful programs using functions with objects in Chapter 12.
We'll focus first on program functions— the functions we create ourselves in our scripts. By learning to create our own functions, we'll become familiar with these fundamentals:
Function declaration
Creating functions to use in our scripts.
Function invocation
Causing functions to execute. In other words, running the code in a function. Also known as calling a function.
Function arguments and parameters
Providing functions with data to manipulate upon invocation.
Function termination
Ending the execution of a function and optionally returning a result.
Function scope
Determining the availability and life span of a function, and the accessibility of variables referenced in a function body.
Once we understand those aspects of functions, we'll consider how they apply to internal functions, functions that come built into ActionScript. Let's get to it!
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Creating Functions
To make a basic function we simply need a function name and a block of statements to perform, like this:
function funcName ( ) {
  statements
}
The function keyword starts the declaration of our new function. Next comes our function name, funcName, which we'll use later to invoke our function. funcName must be a legal identifier. Next, we supply a pair of parentheses, ( ), that enclose any optional parameters, which we'll discuss later. If our function does not have any parameters, we leave the parentheses empty. Finally, we provide the function body (i.e., statement block), which contains the code that's executed when our function is called.
Let's make a (very) simple function:
  1. Start a new Flash movie.
  2. On frame 1 of the main movie timeline, attach the following code:
    function sayHi ( ) {
      trace("Hi there!");
    }
That was easy—we've just created a function named sayHi( ). When we run it, the trace( ) statement in its body will be executed. Don't close the movie you've created, we'll learn to run our function next.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Running Functions
We run a function like a wizard invokes a spell, by proclaiming the function's name, followed by the function call operator, ( ), introduced in Chapter 5:
               funcName( )
(You can almost detect the faint odor of smoldering mandrake root in the air.)
The parentheses may contain any parameters defined by the function. If the function defines no parameters, the parentheses are left empty. Let's try invoking our sayHi( ) function, which has no parameters, to get the hang of basic function invocation.
Here, again, is our sayHi( ) function declaration:
function sayHi ( ) {
  trace("Hi there!");
}
And here's our sayHi( ) function invocation:
sayHi( );
When that line is executed, sayHi( ) is invoked, so its function body runs, causing "Hi there!" to appear in the Output window.
You can see that typing sayHi( ); is more convenient than typing the whole trace( ) statement, and the function name sayHi is a more meaningful description of what our code does. Using thoughtful function names makes our code more readable, almost like human sentences.
Before we continue, notice the semicolon at the end of the function call:
sayHi( );
We add the semicolon because a function call is a complete statement, and good form dictates that all statements should end in a semicolon.
Believe it or not, we've just learned the basics of creating and invoking functions. Not too shabby. Functions keep your code centralized and easier to maintain, especially when you need to perform the same operation repeatedly throughout your program. Functions become even more powerful when used with parameters, which we'll consider next.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Passing Information to Functions
In the last section, we created a function that executed a simple trace( ) statement—not exactly the most compelling specimen of the function species. Here's a more interesting function that moves a movie clip instance named ball a short distance:
function moveBall ( ) {
  ball._x += 10;
  ball._  y += 10;
}
With the function moveBall( ) defined, we can move ball diagonally anytime by calling the moveBall( ) function:
moveBall( );
The ball moves diagonally down and to the right. (Note that the origin (0, 0) is in the upper left of the main Stage. Increasing values of _x move the ball to the right, but unlike the Cartesian coordinates, increasing values of _ y move the ball down, not up.)
Our moveBall( ) function is convenient, but it lacks flexibility. It works only on one movie clip (ball), it moves ball in only one direction, and it always moves ball the same distance.
A well-designed function should define a single code segment that works in many circumstances. We can generalize our moveBall( ) function so that it can move any clip any distance in any direction. The first step in generalizing any function is determining what factors control its behavior. In our moveBall( ) function, the factors are the name of the movie clip to move, the distance to move it horizontally, and the distance to move it vertically. Such factors are known as the parameters of the function—they're the information that we'd like to be able to adjust when the function is called.
Recall the generic syntax of a simple function declaration:
function funcName ( ) {
  statements
}
To add parameters, which are variables that can be used within a function, we provide a list of legal identifiers between the parentheses of a function declaration. Parameters are separated by commas as shown here:
function funcName (param1, param2, param3,...paramn) {
  statements
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Exiting and Returning Valuesfrom Functions
Unless instructed otherwise, a function will end naturally when the interpreter finishes executing the last statement in the function's body. You can, however, terminate a function before the last statement is reached. Additionally, a function can return a result (send back a calculated value) to the code that invoked it. Let's see how these things work.
The return statement, which was introduced in Chapter 6, can be used to terminate a function and, optionally, to return a result. When the interpreter encounters a return statement during a function execution, it skips any remaining statements in the function. Consider this example:
function say(msg) {
  return;
  trace(msg);         // This line is never reached
}
The preceding example is not realistic because its return statement always causes the function to end before the trace( ) statement is reached. Therefore, the return statement is normally the last statement in a function body unless it is used inside a conditional statement. In this example, we use return to exit if the password is not correct:
var correctPass = "cactus";
function enterSite(pass) {
  if (pass != correctPass) {
    // Exit if the password is wrong
    return;
  }
  // This code is reached only if the password is correct
  gotoAndPlay("intro");
}

enterSite("hackAttack");  // Function will exit prematurely
enterSite("cactus");      // Function will end naturally
As its name implies, return tells the interpreter to return to the location of the function invocation. If no return statement is present, ActionScript acts as if the last line of the function body contains a return statement:
function say(msg) {
  trace(msg);
  return;              // This line is completely optional in this context
}
Regardless of whether the return statement is implied or explicit, whenever a function terminates, execution resumes at the line of code following the function-call statement. For example:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Function Literals
ActionScript allows us to create function literals, which are convenient when we need a function temporarily or when we'd like to use a function where an expression is expected.
Function literals have the same syntax as standard function declarations except that the function name is omitted and there's a semicolon after the statement block. The general form is:
function (param1, param2, ... paramn) { statements };
where param1,param2,...paramn is an optional list of parameters and statements is one or more statements that constitute the function body. Because it doesn't include a function name, a function literal is "lost" unless we store it in a variable (or an array element or object property). We can store a function literal in a variable for later access, like this:
// Store a function literal in a variable
var mouseCoords = function ( ) { return [ _xmouse, _  ymouse ]; };

// Now we can execute the function
mouseCoords( );
Note that because ActionScript does not support JavaScript's Function( ) constructor, dynamic functions cannot be composed at runtime, as they can in JavaScript.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Function Availability and Life Span
Like variables, program functions do not live forever and are not directly accessible throughout a movie. In order to invoke functions with confidence, we need to know how to access them from different areas of our movie, and we need to be sure that they exist before we call them.
Program functions (the functions we create ourselves in our code) are directly accessible for invocation only from:
  • Code attached to the timeline of the movie clip that bears the function declaration
  • A button on the timeline of the movie clip that bears the function declaration
By "directly accessible," we mean that the function can be invoked simply by name, without reference to a movie clip or object, like this:
myFunction( );
Functions are also indirectly accessible (i.e., remotely accessible) from any point in a movie using dot syntax. As when referring to variables remotely, we must include the path to the movie clip that contains the function, such as:
myClip.myOtherClip.myFunction( );
_    parent.myFunction( );
_root.myFunction( );
So, suppose a clip instance named rectangle on the main timeline contains a function named area( ). We may invoke area( ) from anywhere in our movie using an absolute path to rectangle, like this:
_root.rectangle.area( );
To reference a function from a remote movie clip timeline, we follow the same rules used when referring to remote variables, as described in Chapter 2. (We'll also learn more about invoking functions remotely in Chapter 13.)
Not all functions are attached to movie clip timelines. Some program functions may be attached to user-defined or built-in objects. When attached to an object, a function is accessible only through its host object. We'll learn more about the availability and life span of
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Function Scope
ActionScript statements have a certain scope, or area of effect within which they are valid. When a statement is attached to a movie clip, that statement's scope is limited to the clip that bears it. For example, here we refer to a variable, score, in an assignment statement:
score = 10;
If that statement were attached to clipA, then the interpreter would set the value of score in clipA, because the statement is "scoped" to clipA. If that statement were attached to clipB, the interpreter would set the value of score in clipB, because the statement is scoped to clipB. The location of the statement determines its scope, and, hence, its effect.
Statements in the body of a function operate in their own, separate scope, called a local scope. A function's local scope is like a private phone booth for the function, distinct from the scope of the clip or object to which the function is attached. The local scope of a function is created when the function is invoked and destroyed when the function finishes executing. When resolving variables referenced in the statements of the function body, the interpreter looks first in the function's scope.
Function parameters, for example, are defined in the local scope of a function—not the scope of the timeline that bears the function. Parameters, hence, are accessible to the statements of a function's body only while the function is running. Statements outside the function have no access to the function's parameters.
A function's local scope provides a place for temporary variables for use solely within a function. This eliminates potential name conflicts between function variables and timeline variables, and it reduces our overall memory usage.
Even though functions operate in their own local scopes, normal timeline variables are still accessible to the statements of a function body. The local scope of a function is the
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Function Parameters Revisited
Now that we're comfortable with how functions work, let's return to the topic of function parameters. Our current discussion requires a little knowledge of objects, so new programmers may want to read Chapter 12 before reading this section.
Earlier we learned that the parameters of a function are declared when the function is created. Recall the syntax:
function funcName (param1, param2, param3,...paramn) {
  statements
}
Perhaps surprisingly, the number of parameters passed to a function can differ from the number specified in the formal function declaration. Functions can accept any number of parameters, whether more than or fewer than the "expected" number. When a function is called with fewer than the declared number of parameters, the value of each missing parameter is set to undefined. For example:
function viewVars (x, y, z) {
  trace ("x is " + x);
  trace ("y is " + y);
  trace ("z is " + z);
}

viewVars(10);  // Displays: "x is 10", "y is ", and "z is " because 
               // y and z are undefined (and display as blanks)
When a function is called with more parameters than the declared number, excess parameter values can be accessed using the arguments object. (Obviously the excess parameters can't be accessed by name like explicitly declared parameters because their names were not declared.)
During the execution of any function, the built-in arguments object gives us access to three pieces of information: (a) the number of parameters that were passed to the function, (b) an array containing each of those parameter values, and (c) the name of the function being executed. The arguments object is really a special hybrid between an array and an object with some other properties.

Section 9.8.2.1: Retrieving parameter values from the arguments array

The
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Recursive Functions
A recursive function is a function that calls itself (by using its own name within its function body). Here's a simple example that shows the principle of recursion. But because the code tells the trouble( ) function to execute repeatedly (like an image reflected infinitely in two opposing mirrors), Flash will quickly run out of memory, causing an error:
function trouble( ) {
  trouble( );
}
Practical recursive functions call themselves only while a given condition is met (thus preventing infinite recursion). Example 9.4 used recursion to count from a specified number down to 1, but obviously that can be accomplished without recursion.
One classic use of recursion is to calculate the mathematical factorial of a number. The factorial of 3 (written as 3! in mathematical nomenclature) is 3*2*1=6. The factorial of 5 is 5*4*3*2*1=120. Example 9.8 shows a factorial function that uses recursion.
Example 9.8. Calculating Factorials Using Recursion
function factorial(x) {
    if (x < 0) {
      return undefined;  // Error condition
    } else if (x <= 1) {
      return 1;
    } else {
      return x * factorial(x-1);
    }
}
trace (factorial(3));  // Displays: 6
trace (factorial(5));  // Displays: 120
As usual, there is more than one way to skin a proverbial cat. Using a loop, we can also calculate a factorial without recursion, as shown in Example 9.9.
Example 9.9. Calculating Factorials Without Recursion
function factorial(x) {
    if (x < 0) {
      return undefined; // Error condition
    } else {
      var result = 1;
      for (var i = 1; i <= x; i++) {
        result = result * i;
      }
      return result;
    }
}
Example 9.8 and Example 9.9 represent two ways of solving the same problem. The recursive method says, "The factorial of 6 is 6 multiplied by the factorial of 5. The factorial of 5 is 5 multiplied by the factorial of 4 . . . " and so on. The nonrecursive method loops over the numbers from 1 to
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Internal Functions
Although we've seen how to create user-defined functions, let's not forget that ActionScript comes with a bevy of built-in functions (akin to verbs in our language analogy). We've already seen some built-in functions that allow us to manipulate data. We've also touched on functions that control the Flash movie and the user environment.
For example, to manipulate the playhead of a movie clip, we can call the gotoAndPlay ( ) function with a frame number as a parameter:
gotoAndPlay(5);
If you are a new programmer, you may be experiencing an epiphany. You hopefully will have noticed that you invoke built-in functions using the function-call operator (the parentheses) and a parameter list (the value 5 in this case) just like our custom user-defined functions! Built-in functions, such as gotoAndPlay( ), are used just like the functions we've been building ourselves. Naturally, the built-in functions do different things than our custom functions, and there is no sense in writing a custom function to do something that a built-in ActionScript function already offers. But like any custom function, each built-in function has a name, optional parameters, and a return value (although sometimes it's undefined).
Even though Flash has long referred to gotoAndPlay as an "Action," we now see it in its true form, as an internal function. In Chapter 6 we learned that some Flash Actions are statements and some are functions. Now that you've studied both thoroughly, you'll be able to tell which are which.
By looking upon certain Actions as functions, you'll have an easier time remembering and using their syntax. For example, to load a movie into the Flash Player we need to know that a loadMovie( ) function exists and what parameters it expects. After a quick jaunt over to Part III, we find the info and can easily put together a statement like this:
loadMovie("myMovie.swf", 1);
Easy stuff once you've become comfortable with using functions.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Functions as Objects
In ActionScript, functions are technically a special type of built-in object. Let's see what that means and how it affects what you can do with functions.
Perhaps surprisingly, we can use any function as an argument to another function like this:
function1(function2);
Note that if there are no parentheses following function2, the interpreter doesn't execute function2( ) but instead just passes its "object reference" as an argument to function1( ). That is, function1( ) receives function2 itself, not the return value of function2( ). Because objects are passed by reference, we can pass a function identifier to another function and it will arrive unscathed. The passed function can be executed like this:
function doCommand(command) {
  command( );      // Executes the passed function
}

// Some examples:
doCommand(stop);  // Pass the internal stop( ) function (stops the current movie)
doCommand(play);  // Pass the internal play( ) function (plays the current movie)
Because functions are a type of object, we may treat them like any other data. In the following example, we assign the internal gotoAndPlay function to the variable gp, which gives us a shorter way to refer to the function:
gp = gotoAndPlay;  // Create a shortcut reference to gotoAndPlay( )
gp(25);            // Invoke gotoAndPlay( ) using our reference
In addition to passing and storing functions as objects, we can exploit the "objectness" of functions by attaching properties to them, like this:
// Create a function
function myFunction ( ) {
  trace(myFunction.x);
}

// Attach a property to it
myFunction.x = 15;

// Check the property value by invoking the function
myFunction( );  // Displays: 15
By attaching properties to functions, we can maintain the state of a piece of information between function executions without cluttering up a timeline with variables.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Centralizing Code
Probably the single most important feature of functions is their reusability—we can create reusable segments of code that can be executed from anywhere in a movie. Because functions can be executed remotely, they can be stored in a central location, easing code maintenance and upgrades.
Suppose, for example, that we have three buttons in three different movie clips, all with the same purpose. Instead of triplicating our code, we can put one copy in a function on the main timeline and invoke it from each button as needed. This saves time, reduces the potential for errors, and makes it easy to update the behavior of all three buttons at once. Because the code is centralized, testing is more reliable and troubleshooting much easier. If one button works and another doesn't, chances are that the problem is in the second button's function invocation and not in your centralized behavior.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The Multiple-Choice Quiz Revisited
In Example 1.1, we introduced new programmers to a simple scripted movie—a multiple-choice quiz. Let's revisit that quiz now to see how we can centralize its code.
Our new quiz's layer structure is set up exactly as before. We'll be changing the code on only the first frame, the quizEnd frame, and the buttons.
You can retrieve the .fla file for both the original and revised versions of the quiz from the online Code Depot.
In our first attempt at creating a multiple-choice quiz, we scattered our code around our movie. We placed the logic of our quiz in three places: on the first frame, where we initialized our quiz; on the buttons, where we tracked the user's answers; and on the quizEnd frame, where we tallied the user's score. We're now going to centralize the quiz logic by performing all of those tasks in the first frame. To initialize the quiz, we'll still use a simple series of statements as we did in the first version, but to track the user's answers and tally the user's score, we'll use two functions, answer( ) and gradeUser( ).
Example 9.10 shows the code on our quiz's first frame. This is where we'll store all the logic needed to run our quiz. Take a look at the code in its entirety, then we'll dissect it.
Example 9.10. A Multiple-Choice Quiz, Version 2
//  Stop the movie at the first question
stop ( );

//  Initialize main timeline variables
var displayTotal;         // Text field for displaying user's score
var numQuestions = 2;     // Number of quiz questions
var q1answer;             // User's answer for question1
var q2answer;             // User's answer for question2
var totalCorrect = 0;     // Number of questions answered correctly
var correctAnswer1 = 3;   // The correct choice for question 1
var correctAnswer2 = 2;   // The correct choice for question 2

//  Function to register user's answers
function answer (choice) {
  answer.currentAnswer++;
  set ("q" + answer.currentAnswer + "answer", choice);
  if (answer.currentAnswer == numQuestions) {
    gotoAndStop ("quizEnd");
  } else {
    gotoAndStop ("q" + (answer.currentAnswer + 1));
  }
}

//  Function to tally user's score
function gradeUser( ) {
  // Count how many questions user answered correctly
  for (i = 1; i <= numQuestions; i++) {
    if (eval("q" + i + "answer") == eval("correctAnswer" + i)) {
      totalCorrect++;
    }
  }

  // Show user's score in an on-screen text field
  displayTotal = totalCorrect;
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Onward!
This chapter showed us one of the most powerful devices in ActionScript: functions. In the next chapter, we'll learn about a special variety of functions, called event handlers, that are executed automatically by the interpreter. Event handlers are one of the key building blocks of interactivity.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 10: Events and Event Handlers
We've learned a lot about composing instructions for the ActionScript interpreter to execute. By now we're pretty comfortable telling the interpreter what we want it to do, but how do we tell it when to perform those actions? ActionScript code doesn't just execute of its own accord—something always provokes its execution.
That "something" is either the synchronous playback of a movie or the occurrence of a predefined asynchronous event.
As a movie plays, the timeline's playhead travels from frame to frame. Each time the playhead enters a new frame, the interpreter executes any code attached to that frame. After the code on a frame has been executed, the screen display is updated and sounds are played. Then, the playhead proceeds to the next frame.
For example, when we place code directly on frame 1 of a movie, that code executes before the content in frame 1 is displayed. If we place another block of code on a keyframe at frame 5 of the same movie, frames 1 through 4 will be displayed, then the code on frame 5 will be executed, then frame 5 will be displayed. The code executed on frames 1 and 5 is said to be executed synchronously because it happens in a linear, predictable fashion.
All code attached to the frames of a movie is executed synchronously. Even if some frames are played out of order due to a gotoAndPlay( ) or gotoAndStop( ) command, the code on each frame is executed in a predictable sequence, synchronized with the movement of the playhead.
Some code does not execute in a predictable sequence. Instead, it executes when the ActionScript interpreter notices that one of a predetermined set of events has occurred. Many events involve some action by the user, such as clicking the mouse or pressing a key. Just as the playhead entering a new frame executes synchronous code attached to the frame, events can cause
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Synchronous Code Execution
As a movie plays, the timeline's playhead travels from frame to frame. Each time the playhead enters a new frame, the interpreter executes any code attached to that frame. After the code on a frame has been executed, the screen display is updated and sounds are played. Then, the playhead proceeds to the next frame.
For example, when we place code directly on frame 1 of a movie, that code executes before the content in frame 1 is displayed. If we place another block of code on a keyframe at frame 5 of the same movie, frames 1 through 4 will be displayed, then the code on frame 5 will be executed, then frame 5 will be displayed. The code executed on frames 1 and 5 is said to be executed synchronously because it happens in a linear, predictable fashion.
All code attached to the frames of a movie is executed synchronously. Even if some frames are played out of order due to a gotoAndPlay( ) or gotoAndStop( ) command, the code on each frame is executed in a predictable sequence, synchronized with the movement of the playhead.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Event-Based AsynchronousCode Execution
Some code does not execute in a predictable sequence. Instead, it executes when the ActionScript interpreter notices that one of a predetermined set of events has occurred. Many events involve some action by the user, such as clicking the mouse or pressing a key. Just as the playhead entering a new frame executes synchronous code attached to the frame, events can cause event-based code to execute. Event-based code (code that executes in response to an event) is said to be executed asynchronously because the triggering of events can occur at arbitrary times.
Synchronous programming requires us to dictate, in advance, the timing of our code's execution. Asynchronous programming, on the other hand, gives us the ability to react dynamically to events as they occur. Asynchronous code execution is critical to ActionScript and to interactivity itself.
This chapter explores asynchronous (event-based) programming in Flash and catalogs the different events supported by ActionScript.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Types of Events
Conceptually, events can be grouped into two categories:
user events
Actions taken by the user (e.g., a mouseclick or a keystroke)
system events
Things that happen as part of the internal playback of a movie (e.g., a movie clip appearing on stage or a series of variables loading from an external file)
ActionScript does not distinguish syntactically between user events and system events. An event triggered internally by a movie is no less palpable than a user's mouseclick. While we might not normally think of, say, a movie clip's removal from the Stage as a noteworthy "event," being able to react to system events gives us great control over a movie.
ActionScript events may also be categorized more practically according to the object to which they pertain. All events happen relative to some object in the Flash environment. That is, the interpreter doesn't just say "The user clicked"; it says, "The user clicked this button" or "The user clicked while this movie clip was on stage." And the interpreter doesn't say, "Data was received"; it says, "This movie clip received some data." We define the code that responds to events on the objects to which the events relate.
The ActionScript objects that can receive events are:
  • Movie Clips
  • Buttons
  • Objects of the XML and XMLSocket classes
As we'll see throughout this chapter, ActionScript actually has two different event implementations: one for events that relate to movie clips and buttons, and one for all other kinds of objects.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Event Handlers
Not every event triggers the execution of code. Events regularly occur without affecting a movie. A user may, for example, generate dozens of events by clicking repeatedly on a button, but those clicks may be ignored. Why? Because, on their own, events can't cause code to execute—we must write code to react to events explicitly. To instruct the interpreter to execute some code in response to an event, we add a so-called event handler that describes the action to take when the specified event occurs. Event handlers are so named because they catch, or handle, the events in a movie.
An event handler is akin to a specially named function that is automatically invoked when a particular event occurs. Creating an event handler is, hence, very much like creating a function, with a few twists:
  • Event handlers have predetermined names such as keyDown. You can't name an event handler whatever you like; you have to use the predefined names shown later in Table 10.1 and Table 10.2.
  • Event handlers are not declared with the function statement.
  • Event handlers must be attached to buttons, movie clips, or objects, not frames.
Most events were first introduced in Flash 5. If exporting to Flash 4 format, use only the button event handlers (only button events were supported in Flash 4), and test your work carefully in the Flash 4 Player.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Event Handler Syntax
The names of events (and their corresponding event handlers) are predetermined by ActionScript. Button event handlers are defined using on (eventName), and movie clip event handlers are defined using onClipEvent (eventName), where eventName is the name of the event to be handled.
Hence, all button event handlers (except keyPres s, which also requires a key parameter) take the form:
on (eventName) {
  statements
}
A single button handler can respond to multiple events, separated by commas. For example:
on (rollover, rollOut) {
  // Invoke a custom function in response to both the rollOver and rollOut events
  playRandomSound( );
}
All movie clip event handlers take the form:
onClipEvent (eventName) {
  statements
}
Unlike button handlers, clip handlers can respond only to a single event.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Creating Event Handlers
To create an event handler, we define the handler and attach it to the appropriate object. We'll begin with the most common handlers—those attached to buttons and movie clips.
To attach an event handler to a button or a movie clip, we must physically place the code of the handler function onto the desired button or clip. We may do so only in the Flash authoring tool, by selecting the object on stage and entering the appropriate code in the Actions panel, shown in Figure 10.1.
Figure 10.1: Attaching an event handler to a button
Let's try making a simple event handler function for both a button and a movie clip. To create a button event handler, follow these instructions:
  1. Start a new Flash movie.
  2. Create a button and drag an instance of it onto the main Stage.
  3. With the button selected, type the following code in the Actions panel:
    on (release) {
      trace("You clicked the button");
    }
  4. Select Control → Test Movie.
  5. Click the button. The message, "You clicked the button," appears in the Output window.
When the movie plays and we press and release the button, the release event is detected by the interpreter and it executes the on (release) event handler. Each time that we press and release the button, the message, "You clicked the button," appears in the Output window.
Now let's try making a slightly more interesting event handler on a movie clip. Once again, follow the instructions:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Event Handler Scope
As with any function, the statements in an event handler execute within a predefined scope. Scope dictates where the interpreter looks to resolve the variables, subfunctions, objects, or properties referenced in an event handler's body. We'll consider event handler scope in relation to movie clip events, button events, and other object events.
Unlike regular functions, movie clip event handlers do not define a local scope ! When we attach a handler to a clip, the scope of the handler is the clip, not just the event handler itself. This means that all variables are retrieved from the clip's timeline. For example, if we attach an enterFrame event handler to a clip named navigation and write trace(x); inside the handler, the interpreter looks for the value of x on navigation's timeline:
onClipEvent (enterFrame) {
  trace(x);  // Displays the value of navigation.x
}
The interpreter does not consult a local scope first because there is no local scope to consult. If we write var y = 10; in our handler, y is defined on navigation's timeline, even though the var keyword ordinarily declares a local variable when used in a function.
The easiest way to remember the scope rules of a clip event handler is to treat the handler's statements as though they were attached to a frame of the handler's clip. For example, suppose we have a clip named ball that has a variable called xVelocity in it. To access xVelocity from inside a ball event handler, we simply refer to it directly, like this:
onClipEvent (mouseDown) {
  xVelocity += 10;
}
We don't have to supply the path to the variable as _root.ball.xVelocity because the interpreter already assumes we mean the variable xVelocity in ball. The same is true of properties and methods; instead of using ball._x, we simply use _x, and instead of using ball.gotoAndStop(5), we simply use gotoAndStop(5). For example:
onClipEvent (enterFrame) {
  _x += xVelocity;                 // Move the ball
  gotoAndPlay(_currentframe - 1);  // Do a little loop
}
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Button Events
Table 10.1 briefly introduces the various events available for buttons. Using button events, we can easily create code for navigation, forms, games, and other interface elements. Let's explore each button event and learn how a button can be programmed to react to mouse and keyboard events.
Each of the button events in Table 10.1 is handled by a matching button event handler of the form on (eventName). For example, the press event is handled using an event handler beginning with on (press). The exception is the keyPress event handler which takes the form on (keyPress key) where key is the key to detect. Button events are sent only to the button with which the mouse is interacting. If multiple buttons overlap, the topmost button receives all events; no other buttons can respond, even if the topmost button has no handlers defined. In the following descriptions, the hit area refers to the physical region of the button that must be under the mouse pointer in order for the button to be activated. (A button's hit area is defined graphically when you create the button in the Flash authoring tool.)
Table 10.1: Button Events
Button Event Name
Button Event Occurs When . . .
press
Primary mouse button is depressed while pointer is in the button's hit area. Other mouse buttons are not detectable.
release
Primary mouse button is depressed and then released while pointer is in the button's
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Movie Clip Events Overview
Movie clip events are generated by a wide variety of occurrences in the Flash Player, from mouseclicks to the downloading of data. Clip events can be broken into two categories: user-input events and movie-playback events. User-input events are related to the mouse and keyboard, while movie-playback events are related to the rendering of frames in the Flash Player, the birth and death of movie clips, and the loading of data.
Note that user-input clip events partially overlap the functionality of the button events described earlier. For example, a clip's mouseDown event handler can detect a mouse press just as a button's press event handler can. Movie clip events, however, are not tied to any kind of hit area like button events are and do not affect the look of the mouse pointer.
Let's spend some quality time with the ActionScript movie clip events, summarized in Table 10.2. We'll look at the movie-playback events first (enterFrame, load, unload, and data) and then see how the user-input events work (mouseDown, mouseUp, mouseMove, keyDown, keyUp). Each of the clip events is handled by a matching clip event handler of the form onClipEvent (eventName). For example, the enterFrame event is handled using an event handler beginning with onClipEvent (enterFrame). With the exception of load, unload, and data, movie clip events are sent to all movie clips on stage even if, say, the user clicks the mouse while on top of a different movie clip (or no movie clip).
Table 10.2: Movie Clip Events
Clip Event Name
Clip Event Occurs When . . .
enterFrame
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Movie-Playback Movie Clip Events
The following events are generated without user intervention as Flash loads and plays movies.
If you've ever resorted to empty, looping movie clips to trigger scripts, enterFrame offers a welcome respite. The enterFrame event occurs once for every frame that passes in a movie. For example, if we place the following code on a movie clip, that clip will grow incrementally by 10 pixels per frame:
onClipEvent (enterFrame) {
  _height += 10;
  _width += 10;
}
(Notice that, as we learned earlier, the _height and _width properties are resolved within the scope of the clip to which the enterFrame event handler is attached, so no clip instance name is required before _height and _width.)
The enterFrame event is generated before each frame is rendered even if the playhead of the clip with the enterFrame handler is stopped. The enterFrame event, hence, is always being triggered.
When displayed in the Flash Player, all Flash movies are constantly running, even when nothing is moving on screen or when a movie's playhead is stopped on a frame. An individual movie clip's enterFrame handler will, hence, be executed repeatedly for as long as that clip is on stage, regardless of whether the clip is playing or stopped. If a clip's playhead is moved by a gotoAndStop( ) function call, the clip's enterFrame event handler is still triggered with each passing frame. And if every playhead of an entire movie has been halted with a stop( ) function, all enterFrame event handlers on all clips will still execute.
The enterFrame event is normally used to update the state of a movie clip repeatedly over time. But an enterFrame event handler need not apply directly to the clip that bears it—e nterFrame can be used with a single-frame, empty clip to execute code repeatedly. This technique, called a
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The User-Input Movie Clip Events
The remainder of the movie clip events relate to user interaction. When any of the user-input clip events occurs, all clips on stage (no matter how deeply nested in other clips) receive the event. Hence, multiple clips may react to a single mouseclick, mouse movement, or keystroke.
To execute code based on the proximity of the mouse to a particular clip, an event handler should check the location of the mouse pointer relative to the clip. The built-in hitTest( ) function provides an easy way to check whether a mouseclick occurred within a certain region, as shown later in Example 10.9.
Like the press button event, the mouseDown clip event detects the downstroke of a mouseclick. The mouseDown event occurs each time the primary mouse button is depressed while the mouse pointer is over any part of the Stage.
Unlike the button press event, mouseDown is not tied to the hit area of a button. In combination with the mouseUp and mouseMove events and the Mouse.hide( ) method, the mouseDown event can be used to implement a custom mouse pointer, as we'll see later in Example 10.8.
The mouseUp event is the counterpart to mouseDown. It occurs each time the primary mouse button is released while the mouse pointer is over any part of the Stage. As with mouseDown, a clip with a mouseUp handler must be present on stage at the time the mouse button is released in order for the event to have any consequence. The mouseUp, mouseDown, and mouseMove events can be used to create rich levels of mouse interactivity without affecting the appearance of the mouse pointer (as a button does).
The mouseMove event lets us detect changes in the mouse pointer's position. Whenever the mouse is in motion,
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Order of Execution
Some movies have code dispersed across multiple timelines and multiple clip event handlers. It's not uncommon, therefore, for a single frame to require the execution of many separate blocks of code—some in event handlers, some on frames in clip timelines, and some on the main timelines of documents in the Player. In these situations, the order in which the various bits of code execute can become quite complex and can greatly affect a program's behavior. We can prevent surprises and guarantee that our code behaves as desired by becoming familiar with the order in which event handlers execute relative to the various timelines in a movie.
Asynchronous event handlers execute independently of the code on a movie's timelines. Button event handlers, for example, are executed immediately when the event that they handle occurs, as are handlers for the mouseDown, mouseUp, mouseMove, keyDown, and keyUp events.
Handlers for the movie-playback events, however, execute in order, according to the progression of the movie, as shown in Table 10.3.
Table 10.3: Movie Clip Event Handler Order of Execution
Event Handler
Execution Timing
load
Executes in the first frame in which the clip is present on stage after parent-timeline code executes, but before clip-internal code executes, and before the frame is rendered.
unload
Executes in the first frame in which the clip is not present on stage, before parent-timeline code executes.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Copying Clip Event Handlers
A quick point that has major ramifications: movie clip event handlers are duplicated when a movie clip is duplicated via the duplicateMovieClip( ) function. Suppose, for example, we have a movie clip on stage called square, which has a load event handler defined:
onClipEvent (load) {
  trace("movie loaded");
}
What happens when we duplicate square to create square2?
square.duplicateMovieClip("square2", 0);
Because the load handler is copied to square2 when we duplicate square, the birth of square2 causes its load handler to execute, which displays "movie loaded" in the Output window. By using this automatic retention of handlers, we can create slick recursive functions with very powerful results. For a demonstration that only scratches the surface of what's possible, refer to Example 10.2.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Refreshing the Screen with updateAfterEvent
As we learned earlier in Section 10.12, the mouseDown, mouseUp, mouseMove, keyDown, and keyUp event handlers are executed immediately upon the occurrence of those events. Immediately means immediately—even if the event in question occurs between the rendering of frames.
This immediacy can give a movie great responsiveness, but that responsiveness can easily be lost. By default, the visual effects of a mouseDown, mouseUp, mouseMove, keyDown, or keyUp event handler are not physically rendered by the Flash Player until the next available frame is rendered. To really see this in action, create a single-frame movie with a frame rate of 1 frame per second, and place a movie clip with the following code on stage:
onClipEvent (mouseDown) {
  _x += 2;
}
Then, test the movie and click the mouse as fast as you can. You'll see that all your clicks are registered, but the movie clip moves only once per second. So, if you click 6 times between frames, the clip will move 12 pixels to the right when the next frame is rendered. If you click 3 times, the clip will move 6 pixels. Each execution of the mouseDown handler is registered between frames, but the results are displayed only when each frame is rendered. This can have dramatic effects on certain forms of interactivity.
Fortunately, we can force Flash to immediately render any visual change that takes place during a user-input event handler without waiting for the next frame to come around. We simply use the updateAfterEvent( ) function from inside our event handler, like this:
onClipEvent (mouseDown) {
  _x += 2;
  updateAfterEvent( );
}
The updateAfterEvent( ) function is available for use only with the mouseDown, mouseUp, mouseMove, keyDown, and keyUp events. It is often essential for smooth and responsive visual behavior associated with user input. Later, in Example 10.8, we'll use updateAfterEvent( ) to ensure the smooth rendering of a custom pointer. Note, however, that button events do not require an explicit
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Code Reusability
When using button events and movie clip events, don't forget the code-centralization principles we learned in Chapter 9. Always try to prevent unnecessary duplication and intermingling of code across movie elements. If you find yourself entering the same code in more than one event handler's body, it may not be wise to attach that code directly to the object. Try generalizing your code, pulling it off the object and placing it in a code repository somewhere in your movie; often the best place is the main timeline.
In many cases, it's a poor idea to hide statements inside a button or clip handler. Remember that encapsulating your code in a function and calling that function from your handler makes your code reusable and easy to find. This is particularly true of buttons—I rarely place anything more than a function-invocation statement directly on a button. For movie clips, you'll need to employ keener judgment, as placing code directly on clips can often be a healthy part of a clean, self-contained code architecture. Experiment with different approaches until you find the right balance for your needs and skill level. Regardless, it always pays to be mindful of redundancy and reusability issues.
For an example of the difference between attaching code to buttons versus calling functions from buttons, see Section 9.12 in Chapter 9.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Dynamic Movie Clip Event Handlers
Early in this chapter, we learned about two kinds of events in Flash—those that are attached to movie clips and buttons and those that are attached to other data objects such as XML and XMLSocket. To create event handlers for data objects, we assign the handler function name as a property of the object. Recall the syntax to add a function dynamically:
myXMLDoc.onLoad = function ( ) { trace("all done loading!"); };
Dynamic function assignment lets us change the behavior of the handler during movie playback. All we have to do is reassign the handler property:
myXMLDoc.onLoad = function ( ) { gotoAndPlay("displayData"); };
Or we can even disable the handler altogether:
myXMLDoc.onLoad = function ( ) { return; };
Unfortunately, handlers of movie clip and button events are not nearly so flexible; they cannot be changed or removed during movie playback. Furthermore, movie clip event handlers cannot be attached to the main movie timeline of any movie! It's impossible to directly create an event handler for a movie's _root clip.
In order to work around these limitations, we can—in the case of the enterFrame and the user-input events—use empty movie clips to simulate dynamic event-handler removal and alteration. Empty movie clips even let us simulate _root-level events. We've already seen the technique in Chapter 8, where we learned how to create an event loop as follows:
  1. Create an empty movie clip named process.
  2. Place another empty clip called eventClip inside process.
  3. On eventClip, attach the desired event handler. The code in the eventClip's handler should target the process clip's host timeline, like this:
    onClipEvent (mouseMove) {
      _ parent._ parent.doSomeFunction( );
    }
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Event Handlers Applied
We'll conclude our exploration of ActionScript events and event handlers with a few real-world examples. These are simple applications, but they give us a sense of how flexible event-based programming can be. The last two examples are available for download from the online Code Depot.
Example 10.7 makes a clip shrink and grow.
Example 10.7. Oscillating the Size of a Movie Clip
onClipEvent (load) {
  var shrinking = false;
  var maxHeight = 300;
  var minHeight = 30;
}

onClipEvent (enterFrame) {
  if (_height < maxHeight && shrinking == false) {
    _height += 10;
    _width  += 10;
  } else {
    shrinking = true;
  }

  if (shrinking == true) {
    if (_height > minHeight) {
      _height -= 10;
      _width  -= 10;
    } else {
      shrinking = false;
      _height += 10;     // Increment here so we don't
      _width  += 10;     // miss a cycle
    }
  }
}
Example 10.8 simulates a custom mouse pointer by hiding the normal system pointer and making a clip follow the mouse location around the screen. In the example, the mouseDown and mouseUp handlers resize the custom pointer slightly to indicate mouseclicks.
Example 10.8. A Custom Mouse Pointer
onClipEvent (load) {
  Mouse.hide( );
}

onClipEvent (mouseMove) {
  _x = _root._xmouse;
  _ y = _root._ymouse;
  updateAfterEvent( );
}

onClipEvent (mouseDown) {
  _width  *= .5;
  _height *= .5;
  updateAfterEvent( );
}

onClipEvent (mouseUp) {
  _width  *= 2;
  _height *= 2;
  updateAfterEvent( );
}
Finally, simply to prove the power of the ActionScript movie clip event handlers, Example 10.9 turns a movie clip into a customized button using mouseMove to check for rollovers, mouseDown and mouseUp to check for button clicks, and the hitTest( ) function to make hit detection a snap. This example assumes that the clip with the handlers has three keyframes labeled up, down, and
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Onward!
With statements, operators, functions, and now events and event handlers under our belt, we've learned how all of the internal tools of ActionScript work. To round out our understanding of the language, in the next three chapters we'll explore three extremely important datatypes: arrays, objects, and movie clips.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 11: Arrays
Back in Chapter 3, we learned that primitive datatypes—strings, numbers, Booleans, null, and undefined—represent basic information in our scripts. We also learned that ActionScript supports several composite datatypes, which can group several pieces of data together into a single datum.
The array type is the first composite datatype we'll study. Arrays are used to store and manipulate ordered lists of information and are, therefore, fundamental tools in sequential, repetitive programming. We use them to do everything from storing values retrieved via a user-input form, to generating pull-down menus, to keeping track of enemy spacecraft in a game. In its most basic form, an array is just a list of items, like your grocery list or the entries in your checkbook ledger.
An array is a data structure that can encompass multiple individual data values, just like a building is a physical structure encompassing multiple floors. Unlike a primitive datatype, an array can include more than one data value. Here is a simple example showing first, two strings, and then an array that contains two strings:
"oranges"              // A single primitive string value
"apples"               // Another primitive string value
["oranges", "apples"]  // A single array containing two strings
An array is a general-purpose container. It can contain any number of items and even items of different types. An array can even contain other arrays. Here is a simple example showing an array containing both strings and numbers. It might represent your shopping list and how many of each item you intend to buy:
["oranges", 6, "apples", 4, "bananas", 3]
Here's another analogy to make the concept of an array a little more tangible. Consider a chest of drawers. An individual drawer contains some content (socks, shirts, etc.). But the chest itself doesn't contain the content; it contains the drawers. The drawers hold the content. The chest organizes the drawers into a single unit.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
What Is an Array?
An array is a data structure that can encompass multiple individual data values, just like a building is a physical structure encompassing multiple floors. Unlike a primitive datatype, an array can include more than one data value. Here is a simple example showing first, two strings, and then an array that contains two strings:
"oranges"              // A single primitive string value
"apples"               // Another primitive string value
["oranges", "apples"]  // A single array containing two strings
An array is a general-purpose container. It can contain any number of items and even items of different types. An array can even contain other arrays. Here is a simple example showing an array containing both strings and numbers. It might represent your shopping list and how many of each item you intend to buy:
["oranges", 6, "apples", 4, "bananas", 3]
Here's another analogy to make the concept of an array a little more tangible. Consider a chest of drawers. An individual drawer contains some content (socks, shirts, etc.). But the chest itself doesn't contain the content; it contains the drawers. The drawers hold the content. The chest organizes the drawers into a single unit.
When we work with an array (the chest of drawers), we are usually interested in the values within the array (the contents of the drawers). The values contained in an array are the information we want to manage. But we may also manipulate the containing structure itself. We may, for example, change an array's size (add or subtract drawers) or reorder its values (swap the contents of its drawers).
Though we speak of an array as containing many values, it's important to recognize that the array itself is a single datum the same way that a string containing multiple characters is still a single string and a number containing several digits is still a single number. As a single datum, an array may be assigned to a variable or used as part of a complex expression:
product = ["ladies downhill skis", 475]  // Store an array in a variable
display(product);                        // Pass that array to a function
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The Anatomy of an Array
Each item stored in an array is called an array element, and each has a unique number (index) by which we can refer to it.
Like a variable, each array element can store any legal datum. An entire array, then, is akin to a collection of sequentially named variables, but instead of each item having a different name, it has an element number (the first element is number 0, not number 1).
Figure 11.1 shows, conceptually, the structure of an array that contains three elements. Element stores the value "Erica", element 1 stores the value "Slavik", and element 2 stores the value "Gary".
Figure 11.1: A sample array structure
To manipulate the values in an array's elements, we ask for them by number. In our chest of drawers analogy we might ask ActionScript to store something in the first drawer or retrieve whatever is in the second drawer for us.
An element's position in the array is known as its index. Just as we can access the seventh character in a string, we can access the seventh element of an array via its index (in this case, the index is 6). We use an element's index to set or retrieve the element's value or to work with the element in various other ways. Some of the array-handling functions, for example, use element indexes to specify ranges of elements for processing.
We can also insert and delete elements from the beginning, end, or even middle of an array. An array can have gaps (that is, some elements may be absent). We may have elements at positions and 4, but nothing in positions 1, 2, and 3. Arrays with gaps are called sparse arrays.
Every array contains a specific number of elements at any given point during its life span. The number of potential elements an array can hold is called the array's
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Creating Arrays
We can create a new array with a data literal (i.e., simply typing out all the elements) or with the special built-in array constructor function, Array( ).
To create an array with the Array( ) constructor, we use the new operator followed by the Array keyword followed by parentheses, which yields an empty array (one with no elements). We normally assign a newly created array to a variable or other data container for future reference. For example:
var myList = new Array( );  // Store an empty array in variable myList
               
We often want to assign initial values to an array's elements. We can do so by passing parameters to the Array( ) constructor when invoking it. Depending on the parameters we supply, the constructor invocation has different effects.
When we supply more than one argument to the Array( ) constructor or when we supply a single nonnumeric argument to the Array( ) constructor, each argument becomes one of the element values in our new array. For example:
var frameLabels = new Array("intro", "section1", "section2", "home");
The array stored in frameLabels would have the following elements:
0: "intro"
 1: "section1"
 2: "section2"
 3: "home"
When we supply exactly one numeric argument to the Array( ) constructor, it creates an array with the specified number of empty placeholder elements:
var myList = new Array(14); // Creates an array with 14 empty elements
Arguments passed to the Array( ) constructor can be any legal expression, including compound expressions:
var x = 10;
var y = 5;
var myNumbers = new Array(x + 1, x * y, Math.random( ));
The myNumbers variable would thus store an array with the following elements:
0: 11
 1: 50
 2: a floating-point number between 0 and 1
                  
               
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Referencing Array Elements
Once we've created an array, we'll inevitably want to retrieve or change the value of its elements. To do so, we can use square brackets (i.e., the array access operator), [], which was introduced in Chapter 5.
In order to obtain an element's value, we simply refer to the element by supplying its index within square brackets, like this:
                  arrayName[elementNumber]
where arrayName must be an array and elementNumber can be any expression that yields a numeric value. The first element is number and the last element number is one less than the array's length. Specifying an element number greater than the last valid element number causes the interpreter to return undefined. For example:
// Create an array using an array literal, and store it in trees
var trees = ["birch", "maple", "oak", "cedar"];

// Display the first element of trees in the Output window
trace(trees[0]);  // Displays: "birch"

// Assign the third element's value to the variable favoriteTree
// (remember indexes start at 0, so index 2 is the third element!!)
var favoriteTree = trees[2];  // favoriteTree becomes "oak"
Now the fun part. Since we can provide the index of an element as any number-yielding expression, we may use variables just as easily as we use numbers to specify an element index. For example:
var i = 3;
var lastTree = trees[i];  // Set lastTree to "cedar"
We can even use function-call expressions that have numeric return values as our array indexes:
// Set randomTree to a randomly picked element of trees
// by calculating a random number between 0 and 3
var randomTree = trees[Math.floor(Math.random( ) * 4)];
Hot dog, that's powerful! You might use a similar approach to pick a random question from an array of trivia questions or to pick a random card from an array that represents a deck of cards.
Note that accessing an array is very similar to accessing a variable value. Array elements can be used as part of a complex expression, as follows:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Determining the Size of an Array
All arrays come with a built-in property named length, which indicates the current number of elements (including empty elements). To access an array's length property, we use the dot operator, like so:
               arrayName.length
An array's length property tells us how many elements are in the array. Here are a few examples:
myList = [34, 45, 57];
trace(myList.length);  // Displays: 3

myWords = ["this", "that", "the other"];
trace(myWords.length);  // Displays: 3, the number of elements, 
                        // not the number of words or characters

frameLabels = new Array(24);      // Note the single numeric argument
                                  // used with the Array( ) constructor
trace(frameLabels.length);  // Displays: 24
The length of an array is always one greater than the index of its last element. For example, an array with elements at indexes 0, 1, and 2 has a length of 3. And an array with elements at indexes 0, 1, 2, and 50 has a length of 51. 51? Yes, 51. Even though indexes 3 through 49 are empty, they still contribute to the length of the array. The last element of an array is always myArray [ myArray .length - 1], because index numbers begin at 0, not 1.
If we add and remove elements, the array's length property is updated to reflect our changes. In fact, we can even set the length property to add or remove elements at the end of an array.
What is an array's length property good for, you ask? Using an array's length property, we can create a loop that accesses all the elements of an array as we saw in Example 8.1. Looping through an array's elements is a fundamental task in programming. To get a sense of what's possible when we combine loops and arrays, study Example 11.1, which hunts through a soundtracks array to find the location of the element with the value "hip hop". You should recognize the for loop from Chapter 8, and the increment operator from Chapter 5. As for the array-access code, well, you just finished learning about that.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Named Array Elements
Elements are usually numbered but can also be named. Using named elements we can emulate so-called associative arrays or hashes . Note that named array elements cannot be manipulated by the Array methods ( push( ), pop( ), etc., covered later) and are not considered part of the numbered element list. An array with one named element and two numbered elements will have a length of 2, not 3. To access all the named elements in an array, therefore, we must use a for-in loop (discussed in Chapter 8), which lists both named and numbered elements.
To add an element that can later be retrieved by name, we use the familiar square brackets, with a string instead of a number, on an existing array:
                  arrayName[elementName] = expression
               
where elementName is a string. For example:
var importantDates = new Array( );
importantDates["dadsBirthday"] = "June 1";
importantDates["mumsBirthday"] = "January 16";
We may also use the dot operator, as follows:
                  arrayName.elementName = expression
               
In this case, elementName must be an identifier, not a string. For example:
var importantDates = new Array( );
importantDates.dadsBirthday = "June 1";
importantDates.mumsBirthday = "January 16";
Assuming that we know an element's identifier (for example, dadsBirthday in the importantDates array), we can access it in one of two ways:
var goShopping = importantDates["dadsBirthday"];
var goShopping = importantDates.dadsBirthday;
Just as is the case when assigning a value to a named element, when accessing an element with square brackets, elementName must be a string or an expression that yields a string. Likewise, when used with the dot operator, elementName must be an identifier (i.e., the element's name without quotes), not a string.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Adding Elements to an Array
You can add elements to an array by specifying a value for a new element, increasing the array's length property, or using one of the built-in array functions.
We can add a new element to an existing array at a specific index by simply assigning a value to that element:
// Create an array, and assign it three values
var myList = ["apples", "oranges", "pears"];

// Add a fourth value
myList[3] = "tangerines";
The new element does not need to be placed immediately after the last element of the old array. If we place the new element more than one element beyond the end of the array, ActionScript automatically creates empty elements for the intervening indexes:
// Leave indexes 4 to 38 empty
myList[39] = "grapes";

trace (myList[12]); // Display is empty because element 12 is undefined
To extend an array without assigning values to new elements, we can simply increase the length property and ActionScript will add enough elements to reach that length:
// Create an array with three elements
var myColors = ["green", "red", "blue"];

// Add 47 empty elements, numbered 3 through 49, to the array
myColors.length = 50;
You might use this approach to create a number of empty elements to hold some data you expect to accumulate, such as student test scores.
We can use built-in array methods to handle more complex element-addition scenarios. (We'll learn in Chapter 12, that a method is a function that operates on an object.)

Section 11.7.3.1: The push( ) method

The push( ) method appends one or more elements to the end of an array. It automatically appends the data after the last element of the array, so we don't need to worry about how many elements already exist. The
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Removing Elements from an Array
You can remove elements from an array using the delete operator, by reducing the length property of an array, or using one of the built-in array methods.
The delete operator sets an array element to undefined, using the following syntax:
delete arrayName[index]
where arrayName is any array, and index is the number or name of the element we want to set to undefined. The name delete is misleading, frankly. It does not remove an element from the array; it merely sets the target element's value to undefined. A delete operation, therefore, is identical to assigning the undefined value to an element. We can verify this by checking the length property of an array after deleting one of its elements:
var myList = ["a", "b", "c"];
trace(myList.length);  // Displays: 3
delete myList[2];
trace(myList.length);  // Still displays 3...the element at index 2 is undefined
                      // instead of "c", but it still exists
To truly delete elements, use splice( ) (to delete them from the middle of an array), or use shift ( ) and pop( ) (to delete them from the beginning or end of an array). Note that delete behaves differently with object properties and named elements than with numbered elements. Using delete on them permanently destroys properties and named elements, leaving no trace of them.
Earlier we used the length property to add elements to an array. We can also set the array's length property to a number smaller than the current length in order to delete elements from the array (i.e., truncate the array):
var toppings = ["pepperoni", "tomatoes", "cheese", "green pepper", "broccoli"];
toppings.length = 3;
trace(toppings);  // Displays: "pepperoni,tomatoes,cheese"
                  // We trimmed elements 3 and 4 (the last two).
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
General Array-Manipulation Tools
Earlier we saw how array methods can be used to remove elements from and add elements to arrays. ActionScript also offers built-in methods for reordering and sorting elements, converting array elements to strings, and extracting arrays from other arrays.
As its name suggests, the reverse( ) method reverses the order of the elements of an array. Simple, but impressive. Here's the syntax:
                  arrayName.reverse( )
And here are the impressive results:
var x = [1, 2, 3, 4];
x.reverse( );
trace(x);  // Displays: "4,3,2,1"
We typically use reverse( ) to reorder a sorted list. For example, if we have a list of products sorted by ascending price, we can display them from least to most expensive, or we can reverse the list to display them from most to least expensive.
Reader Exercise: Try to write your own custom function to reverse the elements in an array. Not only is it harder than it looks, you'll most likely find that the built-in reverse( ) method is substantially faster.
The sort( ) method rearranges the sequence of elements in an array according to an arbitrary rule that we provide. If we provide no rule, sort( ) places the elements in (roughly) alphabetical order by default. Sorting an array alphabetically is really easy, so let's see how that works first:
                  arrayName.sort( )
When we invoke an array's sort( ) method with no arguments, its elements are temporarily converted to strings and sorted according to their code points as shown in Appendix B (see "Character order and alphabetic comparisons" in Chapter 4, for important details):
// This works as expected...
var animals = ["zebra", "ape"];
animals.sort( );
trace(animals);  // Displays: "ape,zebra"
                 // Cool! What a handy little method.

// Watch out, the sort order is not strictly alphabetical...The
// capital "Z" in zebra comes before the lowercase "a" in "ape".
var animals = ["Zebra", "ape"];
animals.sort( );
trace(animals);  // Displays: "Zebra,ape". Oops. See Appendix B.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Multidimensional Arrays
So far we've limited our discussion to one-dimensional arrays, which are akin to a single row or a single column in a spreadsheet. But what if we want to create the equivalent of a spreadsheet with both rows and columns? We need a second dimension. ActionScript natively supports only one-dimensional arrays, but we can simulate a multidimensional array by creating arrays within arrays. That is, we can create an array that contains elements that are themselves arrays (sometimes called nested arrays).
The simplest type of multidimensional array is a two-dimensional array, in which elements are organized conceptually into a grid of rows and columns—the rows are the first dimension of the array, and the columns are the second.
Let's consider how a two-dimensional array works with a practical example. Suppose we're processing an order that contains three products, each with a quantity and a price. We want to simulate a spreadsheet with three rows (one for each product) and two columns (one for the quantity and one for the price). We create a separate array for each row, treating the elements as columns:
var row1 = [6, 2.99];   // Quantity 6, Price 2.99
var row2 = [4, 9.99];   // Quantity 4, Price 9.99
var row3 = [1, 59.99];  // Quantity 1, Price 59.99
Next, we place the rows into a container array named spreadsheet:
var spreadsheet = [row1, row2, row3];
Now we can find the total cost of the order by multiplying the quantity and price of each row and adding them all together. We access a two-dimensional array's elements using two indexes (one for the row and one for the column). The expression spreadsheet[0], for example, represents the first row's two-column array. Hence, to access the second column in the first row of spreadsheet, we use spreadsheet[0][1]:
// Create a variable to store the total cost of the order
var total;

// Now find the cost of the order. For each row, multiply the columns
// together, and add that to the total.
for (var i = 0; i < spreadsheet.length; i++) {
	total += spreadsheet[i][0] * spreadsheet[i][1];
}

trace(total);  // Displays: 117.89
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The Multiple-Choice Quiz, Take 3
In Example 9.10, we revised the multiple-choice quiz from Example 1.1. At that time, we improved the quiz code by creating reusable, centralized functions. Now that we've studied arrays, we can return to the quiz to make a few more improvements. This time, we'll see how to use arrays to store both the user's answers and the correct answers for each question, making our code more succinct, legible, and easier to extend if we want to add new questions.
All the changes we need to make to the quiz this time take place on the scripts layer of frame 1, where our main quiz code is located. Both the previous version and this updated version of the quiz can be found in the online Code Depot. To see what improvements we'll make this time around, read through the code in Example 11.7, paying special attention to the comments.
Example 11.7. A Multiple-Choice Quiz, Version 3
stop( );
//  *** Init main timeline variables
var displayTotal;               // Text field for displaying user's final score
var numQuestions = 2;           // Number of questions in the quiz
var totalCorrect = 0;           // Number of correct answers
var userAnswers = new Array( );  // Array containing user's guesses
var correctAnswers = [3, 2];    // Array containing each question's correct answer
// Notice that we no longer need to maintain two long lists of variables 
// named q1answer, q2answer, etc., and correctAnswer1, correctAnswer2, etc.
// We now store that information conveniently in an array.

// *** Function to register the user's answers
function answer (choice) {
  // Since we can now check how many answers have been given via the
  // length property of userAnswers, we no longer need to manually track
  // that information with the answer.currentAnswer property. Note also 
  // that we have done away with the unwieldy set statement that previously
  // assigned the user's answer to a dynamically named variable.

  // Tack the user's answer onto our array
  userAnswers.push(choice);
  // Do a little navigation, baby
  if ((userAnswers.length) == numQuestions) {
    gotoAndStop ("quizEnd");
  } else {
    gotoAndStop ("q"+ (userAnswers.length + 1));
  }
}

// *** Function to tally the user's score
function gradeUser( ) {
  // Count how many questions were answered correctly. Our
  // 
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Onward!
This chapter gave you an introduction to—and considerable practice using—your first composite datatype, arrays. Now that you understand how multiple pieces of data can be represented within a single container, you have a solid foundation to take into the next chapter. There we'll explore an even more powerful type of composite data—and a fundamental component of ActionScript—objects.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 12: Objects and Classes
This chapter covers so-called object-oriented programming (OOP), which is new territory for many readers. We'll cover some of the terminology and show some applied examples to make it all concrete. You may have heard that OOP is some big mystery or that it's difficult to understand. Quite the contrary, the concepts are highly intuitive and the OOP process much easier than you may have been led to believe. At its heart, OOP simply means that you treat portions of your program as self-contained objects. This is easy to grasp once you realize that everything you deal with in the real world is a self-contained object. Your dog, your parents, your car, and your computer are all self-contained objects meaning that they do some things independently and do other things at your request even if you don't know the inner details of how they work.
You don't have to be a biologist to get your dog to fetch a stick; you don't need to be a mechanical engineer to drive your car; you don't need to be a psychoanalyst to interact with your parents; and rumors to the contrary, you don't need to be a computer scientist to check your email. All you need to know is the commands an object is willing to obey (which are called methods ) and the results those commands produce. For example, if you press the gas pedal of your car, you can expect it to accelerate. If you tell your dog to sit, you can expect him to sit. Armed with this commonsense context of what an object is in the real world, let's see how to relate these concepts to ActionScript.
The classic example of a programming object is a bouncing ball. Like a real ball, a ball object can have properties that represent its attributes, such as its radius, color, mass, position, and bounciness (elasticity). To represent our bouncing ball in a program, we'll create a ball object with a radius property and so forth. The properties of an object represent its state at any given time, but some of its properties change over time. For example, to make our ball move, we need to simulate Newton's laws of motion. That is, we need to describe in computer terms how a ball moves over time. In the simplest case, recalling that speed multiplied by time equals distance, we can determine a ball's horizontal position in the future using this pseudoequation:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The Anatomy of an Object
Like an array, an individual object is a container of containers. An array holds multiple data values in individual elements ; an object, analogously, holds multiple data values in individual properties. The properties of an object, however, are named, not numbered. An array stores a group of elements in a numbered list, but an object stores properties according to unique identifiers that are not arranged in any specific order. To access an array element, we need to know its numeric position, but to access an object property, we need to know its name (i.e., identifier).
Figure 12.1 depicts the properties of a sample object called ball. The ball object contains two properties: radius and color. The values of those properties are 50 and 0xFF0000 (the hex value of red). The properties are named with unique identifiers, much like variables. Even though each property has its own name, all are contained by the single encompassing object, ball.
Figure 12.1: A sample object structure
Obviously an object typically defines properties that are meaningfully related. More specifically, the properties of an object should be chosen in such a way that they would help distinguish one instance of the object from another. Movie clip objects, for example, have properties specific to movie clips, such as their number of frames ( _totalframes) and position ( _x and _ y).
Because object properties are named, not numbered, objects do not have any of the element-management tools of arrays (shift( ), unshift( ), push( ), splice( ), etc.). Object properties are traditionally set via methods of the object to preserve the encapsulated nature of an object. That is, in strict OOP, an object should set its own properties. If an outside entity wants to set an object's property, it should be done by calling an appropriate method of the object. For example, a purist would frown on setting the
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Instantiating Objects
Although it may sound backward, let's assume that we have already created an object class. This assumption isn't too ludicrous, because ActionScript provides many built-in classes, and the custom classes we'll build will behave similarly. Assuming we have an object class, we have to create a specific object instance (i.e., a copy) based on the class. For example, ActionScript provides the Array object class, but it is up to us to create individual arrays.
To create an instance of an object (i.e., instantiate the object), we use the new operator with a constructor function, which is used to initialize the object. The general syntax is:
new ConstructorFunction( )
Let's instantiate our first object using a constructor that's already built into ActionScript: the Object( ) constructor. The Object( ) constructor creates a completely generic object (hence its name), the foundation object type upon which all other object types are based. The following code creates a new generic object:
new Object( )
When we instantiate an object, we normally store the resulting instance in a variable, array element, or object property for later access. For example:
var myObject = new Object( );
Instantiating an object in this manner gives us an empty object with no properties and only two very general methods. Generic objects, hence, are of limited use—the real power of objects comes with specialized object classes. Before we learn how to make our own classes, we'll see how to use object properties and methods with objects of existing classes.
Additional content appearing in this section has been removed.
Purchase this book now or