Translated by William Rodarmor
Price: $24.95 USD
£14.95 GBP
Cover | Table of Contents | Sample Chapter
ball_one bounce around the screen."
http://www.moock.org/webdesign/flash/contact.html.undefined
(indicating the absence of data).var speed; var bookTitle; var x;
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.var x, y, z;
variableName = value;
bookTitle = "ActionScript: The Definitive Guide";
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).speed = 25; output = "thank you";
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.y the value of the expression 1 + 5:y = 1 + 5;
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: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
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.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
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.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
x, in frame
1 of the main timeline. After creating x, we set
its value to 10:var x; x = 10;
trace(x);
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);
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.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.secretPassword on frame
1, we create a function that compares the user's guess to the
real password. Here's our code: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
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)));
010101010101010110101011011010101010101010000010101010101011010101010 101010101010101011101010101010101010101010101010111110101010101010101 010101010101010101010101011101010101010101010101010101010101010101010
010101010101010110101011011010101010101010000010101010101011010101010 101010101010101011101010101010101010101010101010111110101010101010101 010101010101010101010101011101010101010101010101010101010101010101010
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.hi
there," ActionScript provides the
string
datatype. A
string is a series of characters (alphanumerics
and punctuation)."loading...please wait" // A string literal 1.51 // A numeric literal ["jane", "jonathan"] // An array literal
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
"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
999 - "Flash";
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;
999
-
NaN yields the value
NaN, which is the final value of our
expression.var custName = "Derek"; var custTitle = "Coding Genius"; var custAge = 30; var custPhone = "416-222-3333";
cust1Name,
cust2Name, cust1Title,
cust2Title, and so on. Yuck! But if we use an
array, we can store our information much more efficiently:MIN_VALUE and
MAX_VALUE properties of the
Number object in Part III,
for a discussion of legal values.http://www.moock.org/asdg/technotes
0723 // 467 in decimal (7*64 + 2*8 + 3*1)
0x723 // 1827 in decimal (7*256 + 2*16 + 3*1) 0xFF // 255 in decimal (15*16 + 15*1)
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
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
dieRoll = Math.random( );
dieRoll = dieRoll * 6 + 1; // Sets dieRoll to a number between 1 and 6.999"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
"Macromedia" + "Flash"
"Macromedia " + "Flash" // Yields "Macromedia Flash"
"Macromedia" + " " + "Flash" // Also yields "Macromedia Flash"
var company = "Macromedia"; var product = "Flash"; // Set the variable sectionTitle to "Macromedia Flash" var sectionTitle = company + " " + product;
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.true to a
variable that tracks the status of a spaceship's firepower:shipHasDoubleShots = true;
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.
}
false:shipHasDoubleShots = false;
false, causing the
single-damage-dose script to execute when a shot hits its target.// userGuess == password will yield either true or false if (userGuess == password) { gotoAndStop("secretContent"); }
// 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;
}
undefined.undefined by default:var velocity;
var velocity = undefined;
undefined, as in:if (myVariable != undefined) {
// myVariable has a value, so proceed as desired...
}
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)
undefined to "" for
the sake of backward compatibility.if (myVar eq "") {
// Don't do anything yet: myVar is undefined
}
undefined to anything other
than "" in a string context, old code like that
would break in the Flash 5 player.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.null. The null value is not
assigned by the interpreter automatically, but rather by us
deliberately.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.null only compares equal to itself and
undefined:null == undefined; // true null == null; // true
* (the multiplication operator) instead of the
X typically taught in grade school. For example,
this multiplies 5 times 6:5 * 6;
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
((x + y) - (Math.PI * radius * radius)) / 2 // Divide the whole thing by 2
var radius = 10; var height = 25; var circleArea = (Math.PI * radius * radius); var cylinderVolume = circleArea * height;
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
((x + y) - (Math.PI * radius * radius)) / 2 // Divide the whole thing by 2
var radius = 10; var height = 25; var circleArea = (Math.PI * radius * radius); var cylinderVolume = circleArea * height;
-x // One operand x * y // Two operands (x == y) ? "true result" : "false result" // Three operands
identifier = expression
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;
x = y = 4; // Set both x and y to 4
y then the value of
y (which is now 4) is assigned to
x.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
counter += 10; xPosition += xVelocity; score /= 2;
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.NaN. This results
in the entire operation yielding NaN. Refer to
Table 3.1 for details on numeric conversion.
operand1 + operand2
+ should be expressions that yield a numeric
value, such as:234 + 5 // Returns 239 (2 * 3 * 4) + 5 // Returns 29
++operand // Prefix increment operand++ // Postfix increment
operand1 == operand2
true; when they differ, it
returns the Boolean value false. For example:var x = 2; x == 1 // false x == 2 // true
==). 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.if (x = 5) {
trace ("x is equal to 5")
}
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")
}
|
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
|
true or false indicating
whether the relationship described in the comparison is accurate
(true) or inaccurate (false).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.
operand1
<
operand2
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
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"
&), 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).var userStatus = "registered";
if (userStatus == "registered") {
// It's okay, let 'em in...
}
userStatus to
"specialGuest."if (userStatus == "registered") {
// Execute legal-user code...
}
if (userStatus == "specialGuest") {
// Execute exact same legal-user code...
}
( ) 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)
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
,)
allows us to evaluate two expressions where a single expression is
expected. It takes the general form:
operand1, operand2
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.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
void expression
typeof operand;
new constructor
delete identifier
false;
otherwise, it returns true, indicating success.
See Chapter 11.var protocol = "http"; // Statement 1 var domain = "www.moock.org"; // Statement 2 var path = "webdesign/flash/"; // Statement 3 getURL(protocol + "://" + domain + "/" + path); // Statement 4
var numFrames;
numFrames. Finally, a
semicolon marks the end of the statement.x):var x; // Simple declaration var x = 10; // Declaration with assignment
if (expression) substatement;
true, can be a single statement such as a variable
declaration statement:if (x == 5) var numFrames = 2;
if (x == 5) {
var numFrames;
numFrames = 10;
play( );
}
{ statement1; statement2; statement3... }|
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)
|
if (the first condition is met) { // Execute this code } else if (the second condition is met) { // Execute this code } ...otherwise { // Execute this code }
if (condition) { substatements }
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.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
}
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"); }
if (condition) { substatements1 } else { substatements2 }
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.var lastName = "Grossman";
var gender = "male";
if (gender == "male") {
trace("Good morning, Mr. " + lastName + ".");
} else {
trace("Good morning, Ms. " + lastName + ".");
}
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");
}
?:). The conditional operator has three operands,
which you'll recognize as analogous to the components of an
if-else
statement series:
condition ? expression1 : expression2;
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:if (condition1) { substatements1 } else if (condition2) { substatements2 } else if (condition3) { substatements3 } else { substatements4 // Catchall if other conditions were not met }
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");
}
// 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");
}
}
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);
}
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.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);
}
if (x == y) {
trace("x and y are equal");
}
if (x == y) trace ("x and y are equal");
if (x == y)
trace ("x and y are equal");
true. A loop,
on the other hand, causes a statement block to be executed
repeatedly, for as long as its test expression remains
true.true:while (condition) { substatements }
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.var i = 3;
while (i < 5) {
trace("x is less than 5");
}
i to 3. Because the variable i
is used in the test expression of the loop, this step is often called
the loop initializationtrue:while (condition) { substatements }
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.var i = 3;
while (i < 5) {
trace("x is less than 5");
}
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.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 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);
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.starParent and place them
randomly on the Stage. Our galaxy will always contain at least one
star, even if numStars is set to 0.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);
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.for (initialization; condition; update) { substatements }
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);
}
var i = 1;
while (i <= 10) {
trace("Now serving number " + i);
i++;
}
var i = 1;
var j = 10;
while (i <= 10) {
trace("Going up " + i);
trace("Going down " + j);
i++;
j--;
}
for (var i = 1, j = 10; i <= 10; i++, j--) {
trace("Going up " + i);
trace("Going down " + j);
}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 }
var ball = new Object( );
ball.radius = 12;
ball.color = "red";
ball.style = "beach";
for (var prop in ball) {
trace("ball has the property " + prop);
}
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]);
}
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.break
form that contains a series of
declared input variables named input01,
input02, and so on.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
trace("Hi there! Welcome to frame 1");
trace("This is frame 2");
gotoAndPlay(1);
Hi there! Welcome to frame 1 This is frame 2 Hi there! Welcome to frame 1 This is frame 2
function funcName ( ) { statements }
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.function sayHi ( ) {
trace("Hi there!");
}
(
), introduced in Chapter 5:
funcName( )
function sayHi ( ) {
trace("Hi there!");
}
sayHi( );
sayHi( );
ball a short distance:function moveBall ( ) {
ball._x += 10;
ball._ y += 10;
}
ball diagonally anytime by calling the
moveBall( ) function:moveBall( );
_x move the ball to the right, but
unlike the Cartesian coordinates, increasing values of _
y move the ball down, not up.)ball), it moves ball in only
one direction, and it always moves ball the same
distance.function funcName ( ) { statements }
function funcName (param1, param2, param3,...paramn) { statements }
function say(msg) {
return;
trace(msg); // This line is never reached
}
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
function say(msg) {
trace(msg);
return; // This line is completely optional in this context
}
function (param1, param2, ... paramn) { statements };
// Store a function literal in a variable
var mouseCoords = function ( ) { return [ _xmouse, _ ymouse ]; };
// Now we can execute the function
mouseCoords( );
myFunction( );
myClip.myOtherClip.myFunction( ); _ parent.myFunction( ); _root.myFunction( );
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( );
score, in an assignment statement:score = 10;
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.function funcName (param1, param2, param3,...paramn) { statements }
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)
function trouble( ) {
trouble( );
}
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
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;
}
}
gotoAndPlay(5);
undefined).loadMovie("myMovie.swf", 1);
function1(function2);
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)
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
// 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
quizEnd frame, and the buttons.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( ).// 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;
}on (eventName) { statements }
on (rollover, rollOut) {
// Invoke a custom function in response to both the rollOver and rollOut events
playRandomSound( );
}
onClipEvent (eventName) { statements }
on (release) {
trace("You clicked the button");
}
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
}
y is defined on
navigation's timeline, even though the
var keyword ordinarily declares a local variable
when used in a function.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;
}
_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
}|
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 |
|
Clip Event Name
|
Clip Event Occurs When . . .
|
|---|---|
|
enterFrame
|
onClipEvent (enterFrame) {
_height += 10;
_width += 10;
}
_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.)|
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. |
square, which
has a load event handler defined:onClipEvent (load) {
trace("movie loaded");
}
square to create
square2?square.duplicateMovieClip("square2", 0);
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.onClipEvent (mouseDown) {
_x += 2;
}
onClipEvent (mouseDown) {
_x += 2;
updateAfterEvent( );
}
myXMLDoc.onLoad = function ( ) { trace("all done loading!"); };
myXMLDoc.onLoad = function ( ) { gotoAndPlay("displayData"); };
myXMLDoc.onLoad = function ( ) { return; };
_root clip._root-level events. We've already seen the
technique in Chapter 8, where we learned how to
create an event loop as follows:process.eventClip inside
process.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( );
}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
}
}
}
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( );
}
up, down, and
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."oranges" // A single primitive string value "apples" // Another primitive string value ["oranges", "apples"] // A single array containing two strings
["oranges", 6, "apples", 4, "bananas", 3]
"oranges" // A single primitive string value "apples" // Another primitive string value ["oranges", "apples"] // A single array containing two strings
["oranges", 6, "apples", 4, "bananas", 3]
product = ["ladies downhill skis", 475] // Store an array in a variable display(product); // Pass that array to a function
var myList = new Array( ); // Store an empty array in variable myList
var frameLabels = new Array("intro", "section1", "section2", "home");
frameLabels would have the
following elements:0: "intro" 1: "section1" 2: "section2" 3: "home"
var myList = new Array(14); // Creates an array with 14 empty elements
var x = 10; var y = 5; var myNumbers = new Array(x + 1, x * y, Math.random( ));
myNumbers variable would thus store an array
with the following elements:0: 11
1: 50
2: a floating-point number between 0 and 1
[], which was introduced in Chapter 5.
arrayName[elementNumber]
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"
var i = 3;
var lastTree = trees[i]; // Set lastTree to "cedar"
// 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)];
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
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
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.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.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.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.
arrayName[elementName] = expression
var importantDates = new Array( ); importantDates["dadsBirthday"] = "June 1"; importantDates["mumsBirthday"] = "January 16";
arrayName.elementName = expression
var importantDates = new Array( ); importantDates.dadsBirthday = "June 1"; importantDates.mumsBirthday = "January 16";
dadsBirthday in the
importantDates array), we can access it in one of
two ways:var goShopping = importantDates["dadsBirthday"]; var goShopping = importantDates.dadsBirthday;
length
property, or using one of the built-in array functions.// Create an array, and assign it three values var myList = ["apples", "oranges", "pears"]; // Add a fourth value myList[3] = "tangerines";
// Leave indexes 4 to 38 empty myList[39] = "grapes"; trace (myList[12]); // Display is empty because element 12 is undefined
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;
length property of an array, or using one of the
built-in array methods.undefined, using the
following syntax:delete arrayName[index]
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
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).
arrayName.reverse( )
var x = [1, 2, 3, 4]; x.reverse( ); trace(x); // Displays: "4,3,2,1"
arrayName.sort( )
// 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.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
spreadsheet:var spreadsheet = [row1, row2, row3];
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.89stop( );
// *** 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
// 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: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.
_totalframes) and position (
_x and _ y).new ConstructorFunction( )
new Object( )
var myObject = new Object( );