|
|
CONTENTS |
|
I suspect that the overview of programming from the previous chapter has made you
This chapter covers:
How to write expressions and statements.
How to use operators in expressions.
How to use conditions (such as if ) and loop structures.
How to practice using this knowledge.
To quickly review, statements are complete "sentences of code" that usually do something. Expressions are more like "phrases" because they don't
do
anything by
It works the same in Flash—the expression
price/2
results in a value. Finally, operators, as part of an expression, perform an operation (often math) on one or more operands. For example, the "plus" operator (
+
)
The key to writing expressions is to always remember that you're only writing part of a larger statement. By themselves, expressions don't do anything; rather, expressions result in a value because they are evaluated. That is, expressions are evaluated and become their result. An expression from real life might be, "The shirt's price minus the discount." If you said, "My credit card's balance is now increased by the cost of the shirt (minus its discount rate)," it becomes a statement that does something. After you can write expressions (segments), you'll have no trouble writing statements.
Let's use the discounted shirt price for practice. Imagine that you previously assigned the variable
price
to the cost of the shirt. It doesn't matter what the
price
was—but let's just say $25 (that is,
price=25
). Also, consider that the discount rate is 10 percent. Interestingly, I'll bet everyone who's ever gone shopping already
price-(price*discount)
You can think of this as a mathematical formula. No matter what the values of price and discount are, the formula works. It always results in the discounted price.
We'll get to statements later in this chapter (in the section, "Types of Statements"). For now, however, there's more to learn about expressions. Notice in the earlier expression about price, I placed parentheses around
price*discount
. In the version with no parentheses—
price-price*discount
— you might think that Flash will execute the first two elements (
price-price
) first—the result of that portion would be zero. Then zero multiplied by
discount
would always equal zero. (What a sale… "All Shirts $0.") So,
Of course, if you want to force Flash to execute the subtraction operation first, you could rewrite the expression as
(price-price)*discount
.
Interestingly, operators each have an associativity of either "
Parentheses in an expression must balance. That is, for every
It is important to understand that just because you balance your parentheses, there's no guarantee that your code will work as expected. For example, the expression
(price-price)*discount
balances just as well as
price-(price*discount)
, but with entirely different results. So, balancing parentheses is just a technical requirement (like spell-checking a document)—making your code logical or work for your purpose is still necessary. Here's a great tip that I personally guarantee will help you: Any time you type an opening parenthesis, immediately type a closing parenthesis and then
Instead of listing every operator here, we'll first look at how operators work, and then explore the ones that
I've said several times that operators operate on one or more operands. To be technical, when an operator operates on a single operand, it is called
unary
(like "uni-cycle"). When operating on two operands, it's called a
binary
operator. Finally, one operator (
?:
) is
The fact is that operators operate differently depending on the context. Even though it's pretty easy to see and understand how operators act differently based on the number of operands because you can quickly see how many operands are present, some operators also perform differently based on the data type of their operands. That is, the same operator can perform a different operation on different data types. Recall from Chapter 4, "Basic Programming in Flash," that the value of a variable can be one of several data types. Let's just consider the Number and String data types (probably the most common and familiar data types). The + operator is either an addition operator or a concatenate (meaning to connect) operator, depending on its operands. If one or both operands are strings, + is a concatenate operator, as in:
first="Phillip"; last="Kerman"; wholeName=first+last;
The expression first+last results in "PhillipKerman" .
If both the operands are numbers, the + operator performs the addition operation, as in:
previousScore=10 currentScore=2 totalScore=previousScore+currentScore;
The expression previousScore+currentScore results in 12 .
This issue can become quite frustrating if you think a variable (say previousScore ) contains a number, but it actually contains the string ("say 10 "). The expression previousScore+2 will result in the string "102" because + acts as the concatenate operator when one or more of the operands are strings. This is likely to happen in Flash when you use a Dynamic (or Input) Text field to display the value of a variable. Even though the field might read 10 ,it's actually the string "10" because the data type of fields is string. By the way, in Chapter 8, "Functions," you'll learn how to treat a string like a number by using the Number() function. Also, later in this chapter, you'll see how certain operators will actually change the data type of their operands in the section, "Using Assignment Operators to Create Statements."
There's no need to get freaked out about operators. Just remember that operators often behave differently depending on their position in an expression and on their operands' data types. In practice, you'll usually select the correct operator without fail. Just learn to recognize the symptoms of such problems. For example, if the numbers you were expecting to grow end up getting longer (such as 10 turning into 101 ) or if your strings are appearing as NaN (meaning "not a number"), you're likely mixing data types or using the operators incorrectly.
Finally, even though an operator operates only on one or two operands, the operand could actually be an expression (really, the result of an expression). This might have been particularly obvious when we discussed parentheses earlier. The example price-(price*discount) has the minus operator operating on the result of an expression (the multiplication part in the parentheses). Figure 5.2 shows how an operand can actually be the result of an expression.
Let's look at the operators used to perform simple arithmetic. These won't change their operands and (when used on number operands) will have expected results.
Add numbers ( + ) results in the sum of two number operands.
Multiply numbers ( * ) results in the product of two number operands.
Subtract numbers ( - ). As a binary operator (that is, with two operands), it results in the difference by subtracting the second number from the first. It can also be used as a unary operator (on one operand) by placing it before the operand (as in -myNum ), in which case it will result in the inverse of the operand. If it's positive, the result is negative; if it's negative, the result is positive.
Divide numbers (
/
) results in the
Modulo ( % ) results in the remainder when you divide the first number by the second. For example, 20%7 results in 6 because after you divide 7 into 20 (two times), you're left with a remainder of 6.
In addition to these, there are two operators ( ++ and -- ) that also perform simple arithmetic. Because they both change their operands, I've decided to discuss these in the "Assignment Operators" section later in this chapter.
Flash enables you to perform many additional math operations through the Math object (discussed later this chapter), but don't discount how such simple operators can be used in expressions. When you look at the following examples, keep two things in mind: All the
|
Average (mean): |
sum/total |
|
Half: |
full/2 |
|
Average (median—that is, the
|
lowest+((highest-
|
|
Price when discounted: |
price-(price*discount) |
|
Compounded interest: |
principal+(principal*interestRate) |
|
Seconds (with
|
milliseconds/1000 |
These examples all use simple arithmetic operators on homemade variables. You can
Finally, I didn't provide any examples of the modulo (
%
) operator—but it is one of the most powerful operators available. It seems so
Comparison operators are used to write expressions that evaluate to either true or false. That's it. You might understand the need for such expressions if you remember that they'll usually reside within a larger statement. For example, by itself the word "true" doesn't mean anything. However, an entire statement that makes sense might be "If your age is greater than 21, you can purchase alcohol." The expression "is greater than 21" always
The comparison operators by themselves are pretty easy to understand. All these operators require two operands in the form first operand, operator, second operand (such as 12>4 , where 12 is first operand , > is the operator , and 4 is second operand ). Let's look at them all.
Greater than ( > ) results in true when the first number is greater than the second.
Less than ( < ) results in true when the first number is less than the second.
Greater than or equal to ( >= ) results in true when the first number is greater than or equal to the second.
Less than or equal to ( <= ) results in true when the first number is less than or equal to the second.
Not equal to ( != ) results in true when the first number is not the same value as the second.
Equality( == ) results in true when the value of the first and second numbers are equal.
Strict equality ( === ) results in true when both the value and data type of the first and second numbers are equal. (See Flash MX's Reference entry for a full description of how the different data types vary.)
You'll see the most practical examples of the comparison operators later in this chapter, but there are several interesting points to make now. Remember that the result of any expression you write with these operators is always either true or false. That is, they can result in nothing except true or false, and false is a
It's interesting that true and false are the two variations of the Boolean data type. However, you can use them within expressions as though they were numbers. True is 1 and false is 0. For example, the expression score*(timesCheated<1) will automatically reduce the value of score (no matter what it is) to 0 if the timesCheated variable is greater than 0. That is, the portion timesCheated<1 evaluates to either true or false (1 or 0). If timesCheated is 0, that portion is true and score is multiplied by 1—and thus is unaffected. If timesCheated is not less than 1, that portion is false and multiplies score by 0 (bringing it down to 0). This is a form of a conditional statement—but much simpler.
The regular equality operator is
Finally, string manipulation is covered in much more detail in Chapter 9, "Manipulating Strings," but it's worth mentioning that the comparison operators work perfectly well on strings. To work intuitively, both operands must be strings. But the expression
"a"<"b"
evaluates as true because
"a"
is earlier in the alphabet. (Uppercase
Logical operators are used to compare one or two Boolean values—expressions that result in either true or false. (Operators "and," and "or," use two operands, whereas "not" uses one.) Commonly you will extend the comparison operators with logical operators to make compound expressions such as "age is greater than 12 and age is less than 20" ("and" being the logical operator in this case). You're actually comparing two expressions (not two single values), but the result of the entire expression must be either true or false. If you use these logical operators on non-Boolean values (such as numbers), any number except 0 will be considered true. If you use them on strings, each string will be true as well.
The "and" operator ( && ) results in true if both operands are true.
The "or" operator ( ) results in true if either (or both) operands are true.
The "not" operator ( ! ) results in true when the operand (following ! ) is not true (that is, it's false).
Here are a few common examples:
|
True if age is a "teen": |
(age>12) && (age<20) |
|
True if either age is greater than 15 or "accompaniedByAdult" is true: |
(age>15) (accompaniedByAdult==true) |
|
True if age is anything except 21: |
!(age==21) |
|
True if age is not a "teen": |
!((age>12) && (age<20)) |
|
True if age is not equal to 21: |
age != 21 |
Even though these expressions should be easy to figure out, there are some interesting elements to note. I included additional parentheses to make these expressions clear. But because the logical operators have very low precedence, the expressions on each side will be evaluated first. That is, age>12&&age<20 works just as well as (age>12) && (age<20), although it might not be as easy to read. Also notice that both operands of the "and" and "or" operators must be a complete expression. For example, age>12 && <20 won't work. It sounds okay in speech (as in "age is greater than 12 and less than 20,"), but in ActionScript, you want to say "age is greater than 12 and age is less than 20."
Finally, there's one trick that is commonly used to abbreviate scripts—but it might not be intuitive to you. The expression
accompaniedByAdult==true
is the same as
accompaniedByAdult
(by itself). So, in this example, I could have said
age>15accompaniedByAdult
. If you don't say "==true," it's
You'll get plenty of practice writing expressions. Remember that they'll always be contained within bigger statements. These concepts should begin to make more sense as you write statements. The best way to learn to write statements and expressions is to first write your objectives and then start to program in pseudo-code (as discussed in Chapter 3, "The Programmer's Approach"). You might notice that in many of my examples, I actually include the pseudo-code version as well.
As I've mentioned countless times, statements
do
things. Often statements do one of two things: either assign values or compare values. A statement could assign a value to the variable
score
. Another statement might compare the user's score to a set of values to determine a grade. Realize that when comparing values, the end result of a statement could be that no action is taken. For example, a statement could compare the
The granddaddy of the assignment operators is the equals sign (
=
). When this operator appears in a statement, you can read
=
as "…is assigned the value of…." That is,
username="Phillip"
can be translated and read
Here are the basic assignment operators:
Assignment ( = ) places the value of the expression on the right into the variable on the left.
Increment (
++
)
Decrement ( -- ) decrements the variable on the left by 1 (that is, it's reduced by 1).
Addition and assignment (
+=
)
Subtraction and assignment ( -= ) decreases the variable on the left by an amount equal to the expression on the right.
Multiplication and assignment ( *= ) multiplies the variable on the left by an amount equal to the expression on the right.
Divide and assignment ( /= ) divides the variable on the left by an amount equal to the expression on the right.
Modulo and assignment (
%=
) assigns the variable on the left a value equal to the remainder of dividing the value of the expression on the right into the value of the variable on the left. It sounds
If these are starting to seem a bit complicated, remember that you only
need
=
. All the other operations can be achieved with
=
. For example,
counter+=10
will increase
counter
by
10
—but so will
counter=counter+10
. It's not important that you memorize these now. Ultimately, the only thing that matters is getting your movie to do what you want. After you
Possibly the best thing about the all the assignment operators (except += ) is that they actually change the operand being assigned (usually on the left side) to a Number data type. Realize that these operators don't serve double duty (that is, they perform only mathematical assignments and don't work with strings). As such, they try to convert their operand into a number. For example, if you had a variable count that contained a string "12" and you wrote the script count++ , the value of count would become 13 (the number, not the string). So, unlike some operators that operate differently based on the data type of the operands, these attempt to convert operands to numbers.
The two assignment operators
=
and
+=
can work with strings as well. For example, if
Although the data type of operands won't make some of the assignment operators perform different operations, the operator's placement (before or after) the operand can make a difference. You can actually place the
++
or
--
in front of or behind the operand, as in
++counter
or
counter++
. The difference is subtle but important. Placing the operator after the operand (
counter++
, called
post-increment
) increments
counter
"returns" the value of the operand
before
the increment
Although the difference between pre- and post-decrement and increment might seem very subtle, there's actually a particular situation in which you might have to use the pre-decrement or pre-increment option. Specifically, when the operand is a value that you're not allowed to change, only pre-decrement or
oneMore=_totalFrames++; oneMore=++_totalFrames;
In either case, _totalFrames can't change. But only the second statement will assign the oneMore variable a value that's one greater than _totalFrames .
Here are a few examples of typical statements that assign values. (Notice that I've thrown in plenty of expressions within the statements.)
Reduce price to half: price=price/2; (You could also use price/=2; )
Calculate a percent correct based on a number of questions: percentCorrect=(numberCorrect/totalQuestions)*100;
Apply a discount to price if age is greater than 64: price=price(discount*(age>64));
Notice that I ended each statement with a semicolon. Flash understands the end of your statement is reached when the semicolon is used. You can't just type a return at the end of the line because both blank spaces and returns are ignored when Flash reads your script. You could actually run all your code along one long (difficult-to-read) line if you separated distinct statements with semicolons.
Writing statements takes the same skill as writing expressions. Similarly, the skill will come with practice. Most people write any such code in segments. That is, it's difficult to write a statement in the same way that you might compose a sentence in speech (in which you almost talk without thinking—let alone thinking about the composition of your
"Okay, I want to double their score if they got the bonus question right. Well, what if they got it wrong? In that case, just leave
score
alone. What can I do to
score
that will leave it untouched? Either add 0 or multiply by 1. Since doubling involves multiplying by 2, I've got an idea: I'll either multiply by 2 or multiply by 1 (depending on the outcome of the bonus question). So far, I have the statement
score*=
in mind. That is,
score
is assigned the value of
score
multiplied by blank. I want "blank" to be either 1 or 2. That is, either
1+0
or
1+1
. For the second number (
+0
or
+1
), I can simply write an expression that evaluates as either false or true. The expression
bonusQuestion==true
will always evaluate as 0 (when
bonusQuestion
is
not
true) or 1 (when
bonusQuestion
is
true). The part on the right (
(1+0)
or
(1+1)
) can be
Perhaps your brain works differently than mine, but this was just a sample of my thought process. By the way, the same exact task could be expressed with countless variations of statements—this is just one solution. Generally, when you're starting out, your expressions will tend to be wordy—that's fine. You'll get more practice writing expressions and statements at the end of this chapter.
Although I've probably said that "statements
do
things" enough times so that you'll never forget, what I failed to mention is that there are built-in statements that also do things. Consider that ActionScript and JavaScript are practically identical, but there are a few Flash-centric actions that only ActionScript contains, such as
gotoAndPlay()
. The ambiguous
We don't need to step through each statement now. You'll pick them up as you write blocks of code. For example, you'll see both return and break in the upcoming section about conditional and loop statements. The point is that all built-in statements are listed under Actions—and that some of them are unique to Flash.
It's only fair to introduce you to objects now. Even though there are seven other chapters dedicated to the finer points of objects (Chapter 7, "The Movie Clip Object;" Chapter 9, "Manipulating Strings;" Chapter 10, "Keyboard Access and Modifying Onscreen Text;" Chapter 11, "Arrays;" Chapter 12, "Objects;" Chapter 13, "Homemade Objects;" and Chapter 14, "Extending ActionScript"), there are a couple of simple objects that will help you immensely as you write statements—namely, the Math object and the Number object. Instead of providing detailed information about objects here, I'll simply show you how to use the Math and Number objects. They're so easy that you really can use them without fully understanding objects. When you get to the workshop chapters, you'll find the Math Object useful in almost every exercise. You'll use it in Workshop Chapter 3, "Creating a Horizontal Slider," (to help determine the percentages) and in Workshop Chapter 11, "Using Math to Create a Circular Slider," (to help determine the angles). In fact, you'll find the Math Object invaluable if you ever want to go beyond simple addition, subtraction, multiplication, and division.
The Math object will give you access to both common mathematical functions as well as a few constants (such as pi). The functions in the Math object (called
). If I first type a 9 and then press the square root button, my calculator "returns" (into the display field) the square root of 9—that is, 3. Within an expression in Flash, you can also type a 9 (or a variable whose value happens to equal 9) and use the Math object's square root method to return the square root into the expression where you used it. The expression looks like this:
Math.sqrt(9)
. (Remember that as an expression, this evaluates to 3, but it doesn't do anything unless you use it in a statement, such as
answer=Math.sqrt(9);
.)
The form for all the Math object methods is Math.methodName() where methodName is the function that you want to use. The parentheses are required for all methods because they often accept parameters. For example, you can't just say Math.sqrt() . Flash needs to know, "Square root of what?" You put the number (or expression that evaluates out as a number) into the parentheses— for example, Math.sqrt(9); Math.sqrt(6+3); Math.sqrt(oneVar+((someExpression*2) +whatever)) . Flash will take the result of the expression in the parentheses, calculate the square root, and finally put the answer in place of the entire expression. (Remember that it's an expression.)
In addition to methods that perform mathematical operations, the Math object has constants. You can tell them apart from the methods because they're listed in all uppercase letters, such as E (Euler's constant—for use in natural logarithms) and PI (the ratio of a circle's circumference to its diameter—used in trigonometry and geometry). They're used like methods except that because they don't accept parameters, the parentheses aren't used. That is, Math.PI (not Math.PI() ) turns into 3.14159… and Math.E into 2.718…. You could probably live your entire life without ever really needing constants. For example, you could just hard-wire 3.14159 every time you needed to use pi in a formula (for example, if you wanted to calculate the circumference of a circle, PI times radius). It's just that the constants are built into ActionScript and they're very accurate—so you might as well use them when you need them. Just remember the constants are all uppercase and don't need or accept parameters; therefore, they don't use parentheses.
Instead of going through all the Math object features (see Figure 5.4)— effectively providing a recap of the last trigonometry course you took (and possibly awakening the long repressed anxieties associated)—we'll just start using them in statements.
Here are a few fun examples of the Math object:
Math.abs(number)
Absolute value. Returns a non-negative version of
number
. For example,
Math.abs(startPoint-endPoint)
returns the distance between
startPoint
and
endPoint
, and it will always be a positive number even if the
endPoint
is a greater number (which would
Math.max(x,y) returns the value of either x or y (whichever is greater). For example, the statement bestScore=Math.max(writtenScrore, verbalScore); will assign the value of bestScore to equal the value of either writtenScore or verbalScore (whichever is greater).
Math.floor(number)
returns the integer portion of a number. (That is, it rounds it down.) For example, given the number of minutes I've worked on this chapter, I can calculate how many full hours that is by using
hours=Math.floor(minutesWorked/60);
. I can combine this with the modulo operator (
%
) we
Math.round(number)
rounds off
number
to the
Math.random() returns a random decimal number between 0 and 1 (but not including 0 or 1—that is, literally between 0 and 1, not inclusive). For example, if you want to return a number between 1 and 100 (inclusive), first set min=1 and max=100 and then use this expression: Math.floor(Math.random()*((max-min)+1))+min . This might not be easy to read, but the idea is that you multiply the random decimal number by 100 (that is, the difference between the max and min plus 1 — that's the part that reads Math.random()*((max-min)+1) ). Assume that Math.random() returns 0.56899 . It will turn into 56.899 when multiplied by 100 . You take that whole expression and strip off the excess decimals (using the floor method), resulting in 56 . Finally, you add the min (at the end of the expression) because it's quite possible that the random number could be 0.00000000001 , which turns into even after you multiply by 100 and use the Floor method (and that's lower than our min ). Also consider that if you multiply the random decimal by 100 (the max ) you'll never quite get to 100 because the random number is always lower than 1 . That last +min eliminates the possibility of going lower than the min ( 1 ) and makes sure that it's possible to reach the max ( 100 ).
|
To return a random integer between min and max , use Math.floor(Math.random()*((max-min)+1))+min |
Just to make things fun, the Math object's trigonometry functions ( Math.sin (angle) , Math.cos(angle) , and Math.tan(angle) ) expect the angle provided to be expressed in radians (not in degrees with which you might be more familiar). Radians and degrees are simply different measurement units— like miles and kilometers. A half-circle has 180 degrees but only pi radians, whereas a whole circle is 360 degrees, or 2 pi (see Figure 5.5.) Therefore, any time you need to convert degrees to radians, you must multiply by Math.PI/180 . That is, 90 degrees is (Math.PI/180)*90 radians (or 1.57….) (Just multiply your degrees by Math.PI/180 to get radians.)
Whereas the trig functions accept angles (in radians, not degrees), the inverse functions (
Math.asin()
,
Math.acos()
, and
Math.atan()
) return angles (naturally, in radians as well). If you want to convert a value represented in radians to degrees, just
divide
by
Math.PI/180
. That is,
1.57
radians is
1.57/(Math.PI/180)
degrees (or
90
). Even though all this might seem like a sick joke from a sadistic
|
To calculate radians from a given value in degrees, use radians=degrees*(Math.PI/180) To calculate degrees from a given value in radians, use degrees=radians/(Math.PI/180) |
Flash provides one trig function that you might never have seen in math class:
Math.atan2()
. As you might know, the plain
Math.atan()
function (or "arc tangent") will help you determine the angle of a corner in a right triangle. Just provide the length of the triangle's
The plain Math.atan() function is fine and dandy when you're in the real world (where moving up increases values). But consider the coordinate system in Flash. The y values decrease when you go up! Consider the second example in Figure 5.6; both the x and y values are really negative numbers. In addition, you have to remember in that case to subtract the value you find from 180. It becomes even more of a hassle when you move into the other quadrants (from 180 degrees to 270 degrees and from 270 degrees to 360 degrees). Luckily, Math.atan2() resolves the entire mess! You just provide Math.atan2() with two parameters: one for the y value and one for the x value. That's it. You'll notice in Figure 5.7 that all the issues with positive and negative values are handled automatically by Math.atan2() . In Workshop Chapter 11, you'll learn how Math.atan2() can make calculating angles a snap.
By now you see how the Math object's methods can be used within expressions. Basically, you're given a suite of mathematical functions through this object. It's pretty easy to use the Math object, but that doesn't mean all your expressions will be easy to write. It also doesn't mean all the other objects are as easy either. For now, just realize that the Math object provides you with many useful functions.
The Number object and Math object are similar in that you can use both of them in expressions without having an intimate understanding of objects. You simply say
Number.methodName()
or
Number.CONSTANT_NAME
. As you can see in Figure 5.8, the Number object consists
I've included this brief discussion now, however, because—in addition to being a simple object—there's another part of ActionScript with the same name. In addition to the Number object, there's a function called Number() that we touched on earlier this chapter. Even though we won't discuss functions fully until Chapter 8, using the Number() function is easy: Number(expressionOrVariable) attempts to convert the value of expressionOrVariable into a number and return the result. So, myNum=Number("100")+1; will convert the string "100" to a number, add 1 to it, and place 101 into myNum . Remember that the addition operator will act differently if one operand is a string (and in our case, turn myNum into "1001" ). Because the word Number is used in both the case of a Number object and the Number function, it can be confusing. The weird part is that if you use the new constructor in front of Number() ,you'll be creating a new instance of the Number object—a different thing entirely, and something that you probably don't want to do. (At least wait until you learn all about objects in upcoming chapters.)
The Number object's constants are easy to use, albeit not particularly exciting. Here they are:
Number.MAX_VALUE is the "largest representable number," meaning a very high number, but one from which you can subtract. For example, you might initialize a variable to equal MAX_VALUE (as in bigNumber= Number.MAX_VALUE ). Then you could subtract from your variable (for a very long time—but not forever).
Number.MIN_VALUE is the smallest number (actually, a negative number).
Number.NEGATIVE_INFINITY is so far into the negative that you can't even add numbers to ever get out. You can use this constant in comparison expressions, but you can't perform operations on "infinity" the way you can with Number.MAX_VALUE and Number.MIN_VALUE .
Number.POSITIVE_INFINITY is like Number.NEGATIVE_INFINITY but positive. Because you can't perform calculations on variables that contain Number.POSITIVE_INFINITY , the most likely usage would be in a comparison expression (such as an if statement—discussed later this chapter). For example, you could check whether a variable or expression is equal to Number.POSITIVE_INFINITY . For example, 1/0 is Number.POSITIVE_INFINITY .
Number.NaN
means "Not a Number." You'll probably see "NaN" by
We've looked at a lot so far in this chapter: expressions, statements, and the operators that hold them together. Also, the Math object was included because it gives you a different set of operators. There's more. Despite the fact that we've seen some perfectly complete statements, we haven't looked at conditional statements (that execute only when certain conditions exist) or loop structures (that repeatedly execute scripts).
Flash executes every line of script that it encounters. If a script is never encountered, it's never executed. And, if a script is
Looping is a way to make a particular script execute repeatedly—either a certain number of times or until a condition is met. This is helpful when you have a lot of code to process, but also when you're not sure how many times the code needs to execute. In the upcoming section on loops, you'll find that loops can save you a lot of typing. Compare the following two pseudo-code descriptions in which a loop would help:
The long way:
Attention Dasher; Attention Dancer; Attention Prancer; Attention Vixen; Attention Comet; Attention Cupid; Attention Donder; Attention Blitzen.
Using a loop:
All reindeer... Attention.
Although this might not explain the ActionScript syntax (it's just pseudo-code after all), the second choice (the loop) is obviously easier to use.
These four structural conditional statements are really variations on the same concept: If a condition is true, Flash should execute a block of code. At the core of all four variations is a kind of "if"—and it's the
A plain if statement will execute the consequences only when the statement is encountered and the condition is true—nothing more. Realize that unless my wife specifies what to do in the event that they're out of jellybeans, I don't need to do anything (of course, I know better). Had she said, "If they have jellybeans, get some; otherwise, get some chocolate," it's clear that I'll be purchasing one item or the other. If the condition is false (that is, if they don't have jellybeans), I am to automatically follow the second part (the "otherwise" or the else statement, if you will). In reality, I can't get chocolate unless they have some, but that's not at issue. In this case, when the initial condition is false, the second part (the else ) is executed every time.
You can make the else statement conditional, too. That is, "If they have jellybeans, get some; otherwise, if chocolate is on sale, get some of that." Realize that there's a distinct possibility that I will come home empty-handed. A plain if statement can skip part of the code; an if else statement will do one or the other instructions; and an if else if statement could easily skip all the code. Let me show the three real-life statements in actual ActionScript—using a few homemade variables (that are assumed to have previous values).
A plain if :
if (jellybeans>0) {
// buy some
}
A regular if else:
if (jellybeans>0) {
// buy some
} else {
// get chocolate
}
An if else if:
if (jellybeans>0) {
// buy some
} else if (chocolateOnSale == true) {
// get chocolate
}
Even though you
can
write an
if
statement with the Actions panel in Normal Mode, I'd recommend (even if just temporarily) going into Expert Mode to do so. I always start by typing the structure of the
if
statement—no conditions, no results… just a skeleton—as
if (condition){
}
This way I won't forget to
If I decide I need to add an else catch-all statement when the condition is not true, I'll add else {} at the end. That is, the code
if (jellybeans>0){
//buy some
}
can have an else provision added, like this:
if (jellybeans>0){
//buy some
} else {
}
Then I'll go back through and make a new line after the opening curly brace that follows the else statement. Adding an else if statement is not much different. Simply add else if (condition){} instead of else {} .
Finally, else if statements can be nested. That is, when one condition is not met (because it's false), another condition is not met, and you can keep adding else if ad infinitum . As such, nested else if statements can become unwieldy. Although it's not as eloquent (or efficient for the computer), I recommend avoiding deeply nested else if statements and instead using a series of independent if statements. For example, you could use all three if statement in sequence, as follows:
if (jellybeans>0){
//buy some
}
if (!(jellybeans>0)){
//buy chocolate
}
if (chocolateOnSale==true){
//buy chocolate
}
There's a logical problem with this code as
each
if
statement is encountered (and
Even if multiple
if
statements aren't all exclusive (which is the problem here), you can still use this more readable format with a little extra work. The
return
statement will cause Flash to bypass the rest of the script in a block of code. Realize that the code could be
My suggestion for a series of if statements is beginning to look like a real pain, considering that even after one condition is met, you want the rest of the if statements to be skipped but you might have more code (at the end) that you want to execute; therefore, you can't simply use return within each if statement. Just to carry this through, one solution would be to set a "flag" variable. That is, above all the if statements, you can type notDone=1; . Then each condition can be expanded from if(mainCondition){} to read if((mainCondition)&¬Done)){} . This script says that if both the original condition (such as jellybeans>0 ) and the condition notDone==1, then execute the code. Finally, instead of using return within (but at the end of each) if statement, use notDone=0; , which will effectively cause Flash to skip the rest of the conditions. The result would look like this:
1 notDone=1;
2 if (jellybeans>0){
3 //buy some
4 notDone=false;
5 }
6 if (!(jellybeans>0)&¬Done){
7 //buy chocolate
8 notDone=false;
9 }
10 if (chocolate=="on sale"&¬Done){
11 //buy chocolate
12 notDone=false;
13 }
14 //the rest of the code
(Recall that the expression including
notDone
on lines 6 and 10 is the same as
notDone==true
.) I'll be the first to admit that this solution is not eloquent, nor is it particularly efficient for the computer. I would argue, however, that compared to a deeply nested
if else if
statement, it's probably easier to read. The sacrifice of making slightly less
|
|
There's another statement (called switch) that can be used like the variations of the if statement. The
switch
statement enables you to avoid deeply nested
if
else if
statements—but only when you're trying to match one of many specific results of a single expression. Consider that my wife gave me these instructions: "If jellybeans cost $1 per
|
The switch statement uses the following form:
switch (expression){
case value1:
//do this
break; //to skip the rest
case value2:
//do that
break; //to skip the rest
}
Where expression is a single expression that could have a variety of different values. For each possible value you expect, replace value1 or value2 . The great thing about switch is that you can account for as many different unique values as you want. Consider the following finished version from my practical example of jellybeans:
switch (pricePerPound){
case 1:
//buy 4 lbs. and buy a chocolate bar
break;
case 2:
//buy one pound
break;
case 3:
//buy one-half pound
break;
}
Notice that cases 1, 2, and 3 don't
switch (username){
case "admin":
//do admin stuff
break;
case "customer":
//do customer stuff
break;
case "supplier":
//do supplier stuff
break;
}
Ignore, for the time being, the fact that the value for
username
could be
"ADMIN"
(all uppercase) and this example would fail to recognize that value. (In Chapter 10, you'll see how to control strings to handle that kind of thing.) However, do notice that if
username
is not one of the three explicit cases shown, nothing happens. That could be what you want, but there's a feature of
switch
that enables you to include a "catch-all" at the end. It looks just like any case, but it reads
case
default:
(no quotes around
default
). Here's a modified version of the
switch (username){
case "admin":
//do admin stuff
break;
case "customer":
//do customer stuff
break;
case "supplier":
//do supplier stuff
break;
case default:
//do catch all stuff
}
You'll get more practice at the end of the chapter in the "Applied Expression Writing" section. For now, however, I recommend that you study the skeleton form of each version of the if statement as well as of the switch statement.
Any loop will execute the same script as many times as you specify, or until a condition you specify is met. Often you don't know exactly how many times you need the code to execute, but you can still refer to the number of loops by reference, such as, "Keep rinsing the spinach until there's no more dirt in the water" and, "For every envelope in that stack,
If you only learn one loop statement, it should be the for loop. Here's the skeleton:
for (init; condition; next) {
//do statement(s) here
}
Let's use the following example for our discussion:
for (n=1; n<11; n++) {
trace("Current iteration is "+n);
}
You can read the skeleton form of this
for
loop as: Starting with
init
, repeat the following while
condition
is true, and on each iteration, do
next
. Therefore, the example says, "Starting with
n=1
, keep doing the
trace
action while
n<11
…, each time incrementing
n
." The
trace
action is executed 10 consecutive times, but the string that is formed looks slightly different on each loop. In the Output window, you'll see "Current Iteration is 1," and then "Current iteration is 2," and so on. Imagine walking through this loop—the
init
says "
n
starts at 1," so the first time the
trace
action is encountered,
n
is 1. Look at the
next
expression to see what will happen the next time through, and you'll see
n++
(meaning that
n
is incremented by 1) and
n
becomes
2
. The
trace
action is executed again. It keeps doing this while the condition—
n<11
—is true. When
n
One tip (just like writing if statements) is that you should start by typing the skeleton and then replace init; condition; next . Another tip is to remember that the condition is the condition that keeps them in the loop—not the condition to get out of the loop. That is, repeat while the condition is true, not repeat until the condition is true. In the earlier example, we wanted to repeat until n reached 11, but the following (updated) script has a problem:
for (n=1; n==11; n++) {
trace("Current iteration is "+n);
}
The problem is that n starts at 1 , but the condition is looking for 11 , so it doesn't have a chance to ever get to 11 —and the entire loop is skipped.
Probably the biggest warning I can give you is to make sure that your loops eventually finish. It's easy to
Because each iteration of a script takes a tiny fraction of a second, 15 seconds is a very long time! Generally, being stuck in a script is likely a symptom of an infinite loop (also called an indefinite loop ). Here's a perfect example of just such a loop:
for (n=1; n>0; n++) {
//anything because this is an infinite loop!
}
The condition ( n>0 ) is true from the beginning and remains so forever! If the "next" expression decremented n instead of incrementing it, this would not be a problem.
Another way to inadvertently create an infinite loop is to forget how
=
for (n=1; n=11; n++) {
//Help, I'm stuck in an infinite loop
}
The problem is that "condition" is n=11 (an assignment). The entire n=11 statement, if evaluated, is 1 (or true). This code loops forever because the condition ( n=11 ) is true and remains so forever. (This mistake messes me up all the time!)
As I mentioned, learning the plain for loop is all you really need . However, the variation for in is also useful. Unlike the if , if else , and if else if statements, the for in loop is not an extension of the plain for loop. The two are entirely different statements. To fully utilize for in loop, it's best to understand arrays and objects—two subjects covered in later chapters. The idea is that the loop will continue to loop "for all the items in the object." Here's an example: "For all the envelopes in that box, do whatever." I'll just show you the skeleton form and one example without fully explaining arrays or objects.
Skeleton form:
for(iterant in object){
//do statement(s) here
}
Example:
allNames=["Dasher", "Dancer", "Prancer", "Vixen", "Comet", "Cupid", "Donder", "Blitzen"]
for(n in allNames){
trace("On "+allNames[n]);
}
The skeleton form has two elements for you to replace: iterant and object . Give iterant any name you want and it becomes a variable that automatically increments from the highest down to the lowest. If there are eight things in your object (as in my example), it starts at 7, returns the value of the 7th item in the array (in my example: Blitzen), and then decreases in every loop until it reaches 0. (Because arrays start counting from 0, the range is 7 down to 0 rather than 8 to 1, as you might expect.) object is the name of your object or array (in this case, the variable allNames , which happens to contain an array of eight items). You don't have to understand arrays fully to imagine how this example works. For now, notice that one way to populate a variable with an array is shown in the first line of the example (use brackets and separate individual values with commas). If you ever need to grab individual elements from an array, you can use the form: arrayName[index], where index evaluates as 0 through the total number of items in the array (minus 1, because arrays count 0,1,2,3, and so on).
Unlike the plain for loop, the for in loop doesn't require that you specify what is supposed to happen on every loop (that is, the "next"). That's because the variable name you use for the iterant automatically goes through all the items in the object (starting at the highest and incrementing down). The two advantages of the for in loop are that you don't have to define the "next" and you don't have to specify a condition to control the number of times the loop repeats. Here's an example of using a plain for loop to achieve nearly the same result as the for in example I showed. Notice that it's not quite as clean, but it works basically the same way.
allNames=["Dasher", "Dancer", "Prancer", "Vixen", "Comet", "Cupid", "Donder", "Blitzen"]
for(n=0; n<8; n++){
trace("On "+allNames[n]);
}
(By the way, instead of hard-wiring 8 in the condition, I could have used allNames.length , which returns the length of the array—but that's something you'll learn in Chapter 11.) Notice that this example is equivalent to, but not the same as, the for in loop. The for in version effectively goes in reverse order (starting with "Blitzen" rather than "Dasher," as is the case here).
Let's look at the statements that execute every time the loop repeats. You can put any statement (or statements) within the loop. You don't have to use the iterant at all. If you want the statement that executes to vary every time the loop repeats, however, the trick is to use the iterant within the statement. All my examples use a plain trace command. However, the string that appears is different in each iteration because the iterant variable is used—either explicitly, as in trace ("Current iteration is "+n); or within an expression, as in trace("On "+allNames[n]);. (This won't reveal the value of n ; rather, it uses n to extract an element in the allNames variable.)
Also realize that you can include as many statements as you want within a loop. You could even make your own iterant or counter that you maintain. You can nest other statements, such as if statements. See whether you can figure out the result of the following nested statement:
for(n=1; n<11; n++){
if(n%2==0){
trace(n+" is even");
} else {
trace(n+" is odd");
}
}
The variable
n
starts at
1
and iterates through
10
. If the expression
n%2
happens to equal
(that is, zero is the remainder when dividing
n
by
2
), the
trace
command displays "n is even" (but
n
is replaced by the value of
n
). Otherwise, the
trace
command "n is odd" appears. By the way, I wrote out this example by first typing the skeleton of the
for
loop, and then inserting a skeleton of the
if else
statement. Finally, I came back through and filled in the data. (And naturally, I had to test it a few times to weed out the
If nothing else, while loops are the easiest to accidentally turn into infinite loops. Basically, you say, "Repeat while this condition is true." If the condition never becomes false, you'll repeat forever. You have to make sure that the condition eventually turns out to be false. The while loop is not suitable for repeating statements while you wait for the user to do something (or to stop doing something). For example, "While the user has the mouse pressed" is a perfectly legitimate concept, but you have to use a different solution for that objective— while loops are just not made for that. A while loop gives you a way to write a script that will repeatedly execute a statement, but because you might not know exactly how many times it is supposed to execute, you can use a while loop while a condition is true. Remember, both for and for in statements require that you specify the number of loops—even if that specification is in reference to a variable, length of an array, or number of items in an object. If, for example, the task is that you keep looping while a variable called found is 0 (or while(found==0) ), the while loop is perfect. (Just make sure that found will eventually become something other than 0, or you'll be stuck in the loop forever.)
Here's the form:
while (condition) {
//do this statement
}
The following example shows that you must take
allNames=["Dasher", "Dancer", "Prancer", "Vixen", "Comet", "Cupid", "Donder", "Blitzen"]
found=0;
n=0;
while (found==0 && n<allNames.length){
if (allNames[n]=="Rudolf"){
found=1;
}
n++;
}
if (found){
trace("Rudolf found in spot " + n);
}
The form is simple: Statements will repeatedly execute while the condition is true. The preceding example is a bit complex, but instead of contriving an unrealistically simple example, it accurately shows the types of provisions necessary when you use the while loop.
Basically, I want the loop to repeat until I find the string "Rudolf"—so the initial condition is
while found==0
(or false). Before the loop, both
found
and
n
are
The previous example shows how while loops require extra maintenance in the form of your own iterating variable that you first initialize and then increment. This is almost always necessary, although occasionally you don't need to do it. For example, if you're trying to create two random numbers, the following statement should work fine:
oneNum=0;
otherNum=0;
while (oneNum==otherNum){
oneNum=Math.random();
otherNum=Math.random();
}
There's a theoretical possibility that on every iteration, both
oneNum
and
otherNum
will be assigned the same random number. The two variables contain the same value at the start (
) and will then repeat while they
Let's review a few final points about loops. The user won't see any visual change on the Stage during the loop. For example, consider the following statement:
for (n=1; n<6; n++){
someClip._x= n*5;
}
You might expect to see someClip 's x position appear at 5, 10, 15, 20, and then 25. It actually does move to those five locations, but you won't see it move. When the loop is finished, you'll see it in the final resting position of 25—but the Stage does not refresh after each loop. (By the way, you can certainly animate a clip by using scripts, as we'll do in the Workshop Chapter 14, "Offline Production," and Workshop Chapter 15, "Creating a Dynamic Slide Presentation"—you just can't do it by using loops.)
Finally, there are two interesting statements that change the flow of a loop. Similar to the way return will skip out of any function or enclosed event (such as on(press) ), both break and continue can make a loop change course. Specifically, the break statement will jump out of any loop (actually, it jumps to the end of the loop), and the continue statement will immediately jump to the top of the loop (that is, iterate) by skipping any further statements within the loop.
Here's an example that shows how the continue statement jumps to the top of a loop:
for (n=1; n<6; n++){
if (n==3){
continue;
}
trace ("A number that's not three is " + n);
}
If the condition ( n==3 ) is true, the continue statement jumps to the top of the loop (to continue) while bypassing the trace statement below. The continue statement effectively says, "Skip the rest of the statements, but continue looping."
The following example shows how the break statement will jump out of a loop:
n=1;
while(true){
//do something
if (n>10 && n%2==0){
break;
}
n++;
}
trace ("The first even number past ten is "+n);
Without the break statement, this loop would repeat forever. When break is executed, Flash jumps to the end of the loop where it is currently enclosed (that is, to where the trace statement appears in this example). This is just a quick way to get out of a loop. Notice, too, that break will jump past the n++ statement (that is, right outside the enclosing curly brace). You also use break in the switch statement. There, it will cause only the remaining cases to be skipped—but any code following the closing brace of the switch statement itself will be encountered. Compared to return , the break statement only jumps past the end of an enclosed loop, whereas return jumps out of the function or the event that started it all (as with on (press) )—most likely skipping a lot more code than a break statement would. For example, if return were used in this example instead of break , the trace statement would be skipped as well.
This chapter is packed with concepts that relate to composing scripts. You've seen a couple of previews of concepts that will come up later (such as arrays and functions), but for the most part, everything in this chapter has to do with writing expressions and statements. The remaining pages provide a chance to practice writing more complex expressions. I'll provide the objective and you should at least try to write the pseudo-code and then (if you can) the actual script. I'll provide my solution with a translation. You should remember two things while you work through these challenges. First, my solution is just one of countless possible solutions. You might very well find a better way to solve the problem. Second, I include many made-up variables. In a real project, these variables would necessarily have their values set earlier or within a different part of the movie. For example, I might use the expression
score>=80
. The idea is that the variable
score
is one that I've been tracking. Perhaps, attached to the button for each correct answer, I used the script:
score=score+10;
. I'm just
Given a minimum (x location, for example) and a maximum x, write an expression that uses a given percent to return an integer midpoint based on percent. That is, if the west coast is at 100 miles longitude and the east
low+ Math.floor((high-low)*(percent/100));
Calculating 50 percent of 3000 is easy. Just use 3000*(50/100) . To determine the width of the United States, for example, you can subtract the longitude of the east coast ( high ) from the west coast ( low ). Our formula so far: (high-low)*(percent/100) . That will usually result in a decimal answer, and using Math.floor() returns the integer portion. Finally, the entire expression is added to low (or the west coast) because you'll want to start counting from there. For example, if the longitude of west coast is 5000 and the east coast is 8000, 50 percent of the difference is still 1500. If you want to end up in the middle of the country, however, you need to add 1500 to 5000—that is, 6500 (by counting from the west coast). Figure 5.10 should help you visualize this problem.
|
To determine a proportional x position between two points, use: xLoc = low + Math.floor( (high-low) * (percent/100) ) |
Build an array that contains the days of the week, as follows:
daysOfWeek=["Sunday","Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
Then write a loop that displays all the days of the week in the Output window (using the trace statement).
daysOfWeek=["Sunday","Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
for (n=0; n<7; n++){
trace(daysOfWeek[n]);
}
After populating the array, our for loop initializes n to (because, remember, the first item in an array is in index 0). Then, while n is less than 7 (the last item in the array is at index 6 ), our trace statement displays the n th item in the array. Notice that the following also works, but displays the days in reverse order:
for (n in daysOfWeek){
trace(daysOfWeek[n]);
}
Write a statement (using if , if else , or if else if ) that sets a variable called grade to A, B, C, D, or F, based on a variable called score, using a scale in which 90-100 is an A, 80-89 is a B, 70-79 is a C, 60-69 is a D, and 0-59 is an F.
grade="F";
if (score>=60){
grade="D";
}
if (score>=70){
grade="C";
}
if (score>=80){
grade="B";
}
if (score>=90){
grade="A";
}
Granted, this isn't the eloquent solution; there are many other possibilities. The way I
What a chapter! Believe it or not, there's more. However, the topics covered in this chapter cover almost all the typical programming tasks that you'll be doing day in and day out. Although many upcoming chapters have interesting and
|
|
CONTENTS |
|