Introduction to ActionScript 2.0/Printable version
This is the print version of Introduction to ActionScript 2.0 You won't see this message or any elements not part of the book's content when you print or preview this page. |
The current, editable version of this book is available in Wikibooks, the open-content textbooks collection, at
https://en.wikibooks.org/wiki/Introduction_to_ActionScript_2.0
Introduction
ActionScript is the programming language used in Flash projects. This book is intended to help anyone, including those without programming experience, to learn ActionScript and programming in general.
Note that if you have programming experience, this book will be quite easy for you. If your previous language is JavaScript, you may even want to skip the some of the 'bare basics' parts.
This book assumes that you know basic Flash operations. Before you start, make sure you can:
- open a new file in Flash
- create a symbol and drag a symbol onto the stage
- set a frame as a keyframe
- import music into Flash
If you do not, check out the official documentation for your version of Flash first.
What this book does not aim to do
edit- This book is not about the production of Flash games or websites. The information presented in this book should be helpful for all novice Flash programmers, not just those who would like to create a game or interactive website.
- This book is not for your PhD thesis. More advanced aspects of ActionScript, such as interfaces and BitmapData, are not covered. To learn more, get a more advanced book or check out the official ActionScript documentation.
- This book is not here to teach you animation. ActionScript is intended for interactive multimedia elements such as games and websites. If you want to learn animation, find a book that teaches you to animate with Flash.
It is often said that ActionScript's simplicity allows non-programmers to program. This is not our aim here; rather, we hope to make you into a programmer through the simple language that is ActionScript. What are you waiting for? Let's start!
Hang on... why am I still learning AS2?
editFirstly, some folks have pre-Adobe versions of Flash that don't support AS3, and don't want to learn FlashDevelop/Flex development. AS2 are obviously the only choice for these people.
Secondly, AS2 is easier for novice programmers. Although some elements of AS2, often with roots in ECMAScript, may be deemed bad practice (weak typing, absolute addresses, user-defined global variables, code inside instances...), this book does not encourage the use of these elements. The reader is strongly recommended to adhere by the principles described in this book, which will not only improve your programming skills but also smooth your future migration to AS3.
Variables and Data Type
Key concepts:
- Data types
- Primitive data types
- Literals
- Data type conversion
- Composite data types and classes
- Variables
- Variable declaration
- Variable initialisation (for primitive data types)
Before we start doing any programming work, we need to work on our basics. Let's start with data types and variables.
What is a data type?
editWhen we work on a Flash project, there are a lot of 'entities' we need to manage: numbers, text, pictures, and so on. A data type is a type of data in our application.
What is a primitive data type?
editA primitive data type is a type of data that isn't based on any other data types. The primitive data types we're going to use are as follows:
Number
(e.g. 1, 3254, 123.045)String
(e.g. "My name is Joe Bloggs", "ActionScript")Boolean
(true
orfalse
)
ActionScript's data types are much simpler than most computer languages. For example, we don't have classes like 'int' or 'double' (like in Java) for numbers; any kind of number can be placed in the Number class. Also, there is no 'char' type - String is already a primitive data type, and if we want to store a character, we can put it in a string. There's only one kind of string: none of that CHAR/VARCHAR business in SQL.
Note the double quotes around the strings. One should always enclose a string with double quotes. The double quotes tells Flash that it's a string, not a variable name or anything else. true
is a Boolean value, while "true" is a string.
The examples above are all examples of literals, which means they never change and aren't contained in a variable. For example, you can't change the value of 3254, can you?
How can I convert between primitive data types?
editDataType(Value) is used to convert between primitive data types:[1]
- To convert a number or Boolean to a string, type String(Value). For example, String(3) yields "3", String(false) yields "false", and String(true) yields "true".
- To convert a Boolean or string to a number, type Number(Value). For example, Number(true) yields 1, Number(false) yields 0, and Number("12") yields 12.
- To convert a number into a Boolean, type Boolean(Value). Boolean(0) yields false and Boolean(1) yields true.
You can't convert from string to Boolean.
Sometimes, primitive data types just aren't enough. we need to use classes.
What is a composite data type?
editAny data type that is not of a primitive data type is a composite data type. Composite data types are called classes.[2] The Object
class is a prototypical object that has nothing inside it whatsoever. Under Object, we have many different classes. We will make our own classes in the third section. For now, we'll stick to using Flash's built-in classes.
Flash has a lot of built-in classes. We will discuss each class in detail in the second section. The most important ones to know are the MovieClip and Array classes.
Whenever we have an object of a particular class, we say that the object is an instance of the class. The name of an instance is, surprisingly enough, called an instance name.
What is a variable?
editEvery entity, of every type, can be stored in a variable
Consider a variable a 'jar'. This jar can be used to store a lot of things. Sometimes, it stores an actual thing; other times, it stores a link to another thing that is too big to put into a jar. (We'll talk about this in the next chapter.)
How can I define a variable?
editNow that you've got this far, you deserve to start your first ActionScript project!
The long way
editOpen Flash and type in the following code in the first frame, press (CTRL+ENTER for Windows or CMD+ENTER for Mac) to compile and run the script:
Code | Result |
---|---|
var Hello:String;
Hello = "Hello world!";
trace(Hello);
|
|
In human language, that means 'Create a new String called 'Hello', give it the value "Hello world!", then print Hello on the output box.
The first line is explained as follows:
- The keyword
var
is put at the beginning of a line whenever you want to define a variable. Hello
is the name of your variable. (The technical term for a variable's name is identifier, but that is unnecessary jargon and we won't use that in this book.)String
is the data type of your variable. (The process of giving your variable a data type is called strong typing your variable.)[3]- The semi-colon is added to the end of each statement. A statement tells the computer to do something. In human language, 'Apples are green' is not a statement; 'eat that apple' is a statement. [4]
As you have probably noticed, the syntax for declaring a variable (i.e. telling the computer to set aside some of its precious RAM to store your variable) is as follows:
var variableName:DataType;
Now let's take a look at the second line. The equal sign is called the assignment operator It is used to assign a value to a variable. In this case, since we're assigned the words 'Hello world!' to the variable.
The third line is a function which prints the words 'Hello world!' on the output screen.[5] A detailed explanation of functions will be given in the chapter on functions. For now, just take it for granted.
A shortcut
editThere's a quicker way to declare a variable and assign a value to it.
Code | Result |
---|---|
var Hello:String = "Hello world!";
trace(Hello);
|
|
This is called initialising a variable.
The syntax for initialising a variable is as follows:
var VariableName:DataType = Value;
How should I name my variable?
editLike most programming languages, ActionScript does not allow certain names.
- All variable names must start with a letter, an underscore (_) or a dollar sign($). Numbers are also allowed after the first character. No other characters should be used.
- From Flash Player 7 on, variable names are case-sensitive. That means thisVariable and thisvariable are two distinct variables.
- Reserved words (words that are used in Flash syntax) cannot be used as variable names.
Here's a list of reserved words:
|
|
|
|
|
|
These words may be used in future releases of Flash, so it's best not to touch them, either, lest your application should go wrong in future versions of Flash Player.
|
|
|
In addition, according to naming conventions, variables should always start with a lowercase letter and consist of words smashed together using CamelCase. For example, instead of $Animalspecies, you should name the variable animalSpecies. There is an exception to this rule, which will be discussed later.
An additional convention for Boolean variables is to use a verb of the third person at the beginning. The most common type is verb to be + complement, such as isHappy, isPaused, etc. Other examples of good Boolean names include likesCheese, hasPimples, and so on.
How can I delete a variable?
editTo delete a variable, we need to use the word 'delete':
Code | Result |
---|---|
var someString:String = "Hello";
delete someString;
trace(someString);
|
|
In this example, we have created deleted the variable 'Hello'.
Note that delete is often problematic. We will discuss this in brief in the second section, and in detail in the third section.
Conclusion
editNow that you have an idea how variables work, let's move on to the second chapter: Operators.
Note
edit- ↑ It can also be used to cast an object into another class, but that will come much later in the book.
- ↑ In ActionScript, primitive data types are 'wrapped' in the Number, String and Boolean classes respectively.
- ↑ In ActionScript 2.0, it is acceptable to write such a declaration:
var Hello; Hello = "Hello world!"; trace("Hello world!");
In this code, the variable's data type is not defined. However, this is a frequent source of error for programmers who may then assign something else - like a number - to Hello. To avoid this error, it is highly recommended that you always declare the data type so that Flash will give you an error when you make such a mistake.
- ↑ The semi-colon is not required in ActionScript (unlike some languages like PHP), but it is strongly recommended that you add it.
- ↑ The output screen will pop up during runtime if you don't already have it in place.
Operators
Key concepts:
- Operators
- Operator types
- Arithmetic operators
- Text concatenation operator
- Comparison operators
- Different types of comparison
- Logical operators
- Assignment operators
- Two types of simple assignment
- Compound assignment operators
- Incremental and decremental operators
- Operator precedence
- Operator associativity
- Comments
- Expressions vs. statements
An operator is something, usually a sign like + or -, that is used to manipulate different entities. The entities manipulated are called operands. If you have experience with programming, SQL or even simple computer languages like spreadsheet formulae, you should be familiar with a lot of them already. In the last chapter, we have already introduced the assignment operator. In this chapter, we will go into detail about the most useful operators. (Note: dot and array access operators are also useful, but we'll save that till later when we learn about properties and methods.)
What are the most useful operators?
editArithmetic operators
editAn arithmetic operator is an operator that does maths for you. The four basic arithmetic operators are as follows:
- + does addition.
- - does subtraction.
- * does multiplication.
- / does division.
Now, you may be tempted to write such a code:
Code | Result |
---|---|
1 + 1;
|
|
However, this will give you an error. This is because 1 + 1 is only an expression with a value of 2; it is not a statement. (Recall: statements tell the computer to do something.) Therefore, we should write this instead:
Code | Result |
---|---|
trace(1 + 1);
|
|
Again, just take the 'trace' thing for granted for now. Enter this into the ActionScript of the first frame and preview your Flash file. '2' should appear on the output box.
In addition to the above, a less frequently used operator, %, can calculate the remainder of a division operation. 10 % 3, for example, returns 1. Other operations (such as exponents, square roots, etc.) cannot be evaluated using operators and we'll learn them later.
Text concatenation operator
editOne peculiarity of Flash is that + acts as both the addition operator and the text concatenation operator. The text concatenation operator turns two strings into one. For example, by concatenating "This is" and " Sparta" (note the space before Sparta), we'll get "This is Sparta". If we concatenate "This is" and "Sparta", however, we'll get "This isSparta", which is undesirable.
If the entites on either side of the + sign are both numbers, the + will act as the addition operator. Otherwise, the + will act as a text concatenation operator. Here's an example:
Code | Result |
---|---|
trace(1 + 1);
trace("1" + 1);
trace(1 + "1");
trace("1" + "1");
|
|
Comparison operators
editComparison operators are operators which compare two entities and return a Boolean value.
Equality operator
editThe equality operator (==) compares two entites and determines whether they are exactly the same. If it's the same, it returns true
; otherwise, it returns false
. Here's some sample code:
Code | Result |
---|---|
trace(1 == 2);
trace(1 == 1);
trace("Hello world" == "Hello world");
trace("This is sparta!" == "This is Sparta!");
|
|
Note that the last one is false because the equality operator is case-sensitive.
When we're working with composite data types, we need to be more careful. The equality operator will only return true
if they are referring to the same entity. Even if we have two distinct identical entities, the equality operator will return false
. In this example, let's imagine there are two dogs. One is called Spot, and it has another name, Bandian (which is Chinese for 'spot'). The other is called 'Lucky' and they are twins, and are physiologically the same in every way.
Code | Result |
---|---|
trace(spot == bandian);
trace(spot == lucky);
|
|
Sometimes, we compare two entities of different data types, such as 23 and "23". In this case, the equality operator will still return true
by automatically converting "23" to 23 for you. If you don't want this automatic conversion, use the strict equality operator (===).
Code | Result |
---|---|
trace(23 == "23");
trace(23 === "23");
|
|
Inequality operators
editFlash provides several inequality operators for all your comparing needs.
The first operator is !=. != does the opposite of ==: if the two are equal, it returns false
, and if the two are unequal, it returns true. Consider the following code:
Code | Result |
---|---|
trace(1 != 2);
trace("2" != 2);
|
|
You've probably noticed that != also converts the data types where necessary. If you don't want that to happen, use !==.
Code | Result |
---|---|
trace("2" !== 2);
|
|
The other four operators are <, >, <= and >=. They do the same as <, >, ≤ and ≥ in mathematics. If you need a quick refresher, here you go:
- < means 'smaller than'.
- > means 'larger than'.
- <= means 'smaller than or equal to'.
- >= means 'larger than or equal to'.
Look at the following example:
Code | Result |
---|---|
trace(12 < 3);
trace(12 > 3);
trace(12 <= 3);
trace(12 >= 3);
trace(12 < 12);
trace(12 > 12);
trace(12 <= 12);
trace(12 >= 12);
|
|
We can also compare strings. No, really! The strings are converted into their Unicode code points in order to be compared. See Unicode/Character reference/0000-0FFF for the code points.
Code | Result |
---|---|
trace("Apple" > "Ball");
trace("Apple" < "Ball");
trace("apple" < "Ball");
trace("apple" != "apple");
|
|
With letters of the same case, later letters have larger values than earlier letters, so a < b and A < B. However, uppercase letters are always smaller than lowercase letters, so a > B.
Logical operators
editLike most languages, the most important logical operators are AND, OR and NOT.
&& is ActionScript's AND operator. Its operands must be Boolean. If both operands are true
, it returns true
; otherwise, it returns false
.
Code | Result |
---|---|
trace(true && false);
trace(false && false);
trace(true && true);
trace(1>0 && 1=1);
trace(1<0 && 1=1);
|
|
|| is ActionScript's OR operator. Its operands must be Boolean. If neither operand is true
, it returns false
; otherwise, it returns true
.
Code | Result |
---|---|
trace(true || false);
trace(false || false);
trace(true || true);
trace(1>0 || 1=1);
trace(1<0 || 1=1);
|
|
Note that there must be two ampersands for AND and two vertical bars for OR.[1]
! (pronounced 'bang') is ActionScript's NOT operator. It is added before the operand.It flips Boolean variables around: false
becomes true
and true
becomes false
.
Code | Result |
---|---|
trace(!false);
trace(!true);
trace(!true && true);
trace(!false && true);
|
|
Assignment operators
editSimple assignment operator
editWe've already met the simple assignment operator in the last chapter, but there's something else we need to clarify first. The simple assignment operator actually does two distinct things:
- With primitive data types, the assignment operator simply copies the assigned value to the variable.
- With other data types, the assignment operator puts a link to the assigned entity inside the variable!
What does this mean?
Code | Result |
---|---|
var string_1:String = "Wikibooks";
var string_2:String = string_1;
string_2 = "Wikipedia";
trace(string_1);
|
|
Here, Flash copied the value "Wikibooks" to string_2. After we changed string_2 to "Wikipedia", the original string_1 is not affected. Consider another situation with a non-primitive data type, Dog:
Code | Result |
---|---|
//Assume that spot is a chihuahua.
var nicestDog:Dog = spot;
nicestDog.species = "pekingese";
|
|
The first line is a comment; we'll talk about that at the end of the chapter. You don't have to understand the third line, either; just assume that it changes the species of nicestDog to 'pekingese'. Now, do you think changing nicestDog's species to 'pekingese' will genetically alter Spot, a chihuahua, into a pekingese? The answer is yes. This is because nicestDog only contains a link to spot.
Compound assignment operators
editThere are two types of compound assignment operators. We will only talk about the type that combines assignment and arithmetic operators. If you're interested, you can check the official Flash documentation to learn about the other type.
Compound assignment operators always work with numbers. There are five of them, each corresponding to one arithmetic operator:
- +=, the addition and reassignment operator
- -=, the subtraction and reassignment operator
- *=, the multiplication and reassignment operator
- /=, the division and reassignment operator
- %=, the modulus and reassignment operator
What these operators do is to perform an operation on the left operand and the right operand, then assign the value to the left operand. In other words,
a += b;
is equivalent to
a = a + b;
Let's better = understand this concept with an example.
Code | Result |
---|---|
var number_1:Number = 5;
number_1 *= 2;
trace(number_1);
|
|
In this example, Flash multiplied number_1 with 5, then assigned the value to number_1.
What do assignment operators return?
editSo far, we've seen that arithmetic operators, logical operators, comparison operators and and the text concatenation operator all return a value. Since assignment operators can be statements per se, does that mean they do not return a value?
In fact, assignment operators do return values. The value returned by an assignment operator is the value assigned to the left operand. For example, a = 2
returns the value 2, while a /= 2
returns half the original value of a.
The following code may look counter-intuitive, but it works:
Code | Result |
---|---|
var a = 6;
var some_number:Number = 3 + (a += 1);
trace(some_number);
trace(a);
|
|
Here, a += 1
returns 7. The round brackets are to allow the operation inside it to be performed first; we'll discuss that later.
Incremental operators
editActionScript offers four incremental/decremental operators:
- The postfix increment operator, written as
variableName++
- The prefix increment operator, written as
++variableName
- The postfix decrement operator, written as
variableName--
- The prefix decrement operator, written as
--variableName
Both incremental operators add 1 to integral variables, and both decremental operators subtract 1 from integral variables. They are statements in their own rights. For example:
Code | Result |
---|---|
var myFirstNumber:Number = 10;
myFirstNumber++;
trace(myFirstNumber);
myFirstNumber--;
trace(myFirstNumber);
++myFirstNumber;
trace(myFirstNumber);
--myFirstNumber;
trace(myFirstNumber);
|
|
As you can see, incremental and decremental operators when the are statements per se. However, we sometimes want to place the incremental operator into another statement. With the postfix increment/decrement operators, everything else will be evaluated before going back to the increment/decrement. With the prefix increment/decrement operators, the increment/decrement will be evaluated before everything else.
If that sounds confusing, look at the following examples:
Code | Result |
---|---|
var myFirstNumber:Number = 10;
trace(myFirstNumber++);
trace(myFirstNumber);
|
|
Code | Result |
---|---|
var myFirstNumber:Number = 10;
trace(++myFirstNumber);
trace(myFirstNumber);
|
|
In our first example, myFirstNumber
was traced before the increment operation. That's why we still see 10 in the first trace statement. The second trace statement displays the computed value 11.
In our second example, myFirstNumber
was traced after the increment operation, so we can already see the 11 in the first trace.
What is the order of operations?
editRemember the order of operations (PEMDAS or BOMDAS/BIMDAS) you learnt in Maths class? ActionScript also applies different operators in a fixed order.
In ActionScript, there are two things we need to consider when determining the order of operations: operator precedence and operator associativity.
What is operator precedence?
editWhen one operator is always evaluated before the other, we call it operator precedence.
Here's a quick lowdown on operator precedence:
- Operators that only involve one operand, such as NOT (!), are the first to be evaluated. (These are called unary operators if you want to know.)
- Next on the list are *, / and %.
- Then we have + and -
- Then come the comparison operators.
- Then the logical operators AND and OR.
- The last ones are the assignment operators.
If we want a certain operation to have higher precedence, we should use the grouping operator, which is a pair of round brackets: ()
. We've already met that before, when we learnt about assignment operators. Let's take another look at that example:
Code | Result |
---|---|
var a = 6;
var someNumber:Number = 3 + (a += 1);
trace(someNumber);
trace(a);
|
|
Here, a += 1 is given priority as it is enclosed in round brackets.
Without the brackets, it would result in an error:
Code | Result |
---|---|
var a = 6;
var someNumber:Number = 3 + a += 1;
trace(someNumber);
trace(a);
|
|
This is because var someNumber:Number = 3 + a
is performed first. var someNumber:Number = 3 + a
returns a value of 6. You can't assign a value to a constant, or the world would be a very chaotic place! That's why Flash will return an error.
What is operator associativity?
editConsider the expression someNumber = 3 * 2 + 5 * 6
. 3 * 2 and 5 * 6 have the same precedence, so which one should be performed first? Operator associativity answers this question. In this case, since the associativity of + is 'left to right', 3 * 2 is evaluated first, then 5 * 6, and finally 6 + 30.
The associativities of +, -, *, /, and % operators are all left to right, while those assignment are right to left.
Let's run a script with lots of operators to see the effects of operator precedence and associativity.
Code | Result |
---|---|
var someNumber:Number;
someNumber = 13 + 5 * 4;
trace(someNumber);
trace(1 + 3 / 5 != 2 && 4 - 3 >= 1);
|
|
In the assignment statement of someNumber, the computer evaluates 5 * 4 first, then 13 + 20.
The second trace is much more complicated. The operator with the lowest precedence here is &&, whose precedence is even lower than the comparison operators. The associativity of && is left to right, so the computer needs to evaluate the code on the left of && (1 + 3 / 5 != 2
) first. 1 + 3 / 5 = 1.6, which is not equal to 2. Therefore, the left side returns the value true
. Now to the right side. In 4 - 3 >= 1
, 4 - 3 = 1, so 1 >= 1 returns true
. Since both sides of the && are true, the trace statement returns true
.
How can I add a comment?
editNow that we've learnt all the difficult operators, let's end the chapter with a very simple concept.
A comment is some text that is added to the script to give information. They will be ignored by the compiler. The following example shows two types of comment:
Code | Result |
---|---|
/*This is just an example.
Don't actually copy-paste this into a Flash file.
There will be no visible results. */
var a = 6;
var someNumber:Number = 3 + (a += 1); //Assign the sum of 3 and a's new value to someNumber
|
|
The first comment, enclosed by /* and */, allows for multiple lines. /* marks the beginning of the comment and */ marks the end of it. This type of comment can also be added in the middle of a line. They are widely used for elements such as to-do lists and copyright information.
The second comment starts with // and is added to the end of the line. It cannot extend over one line. This type of comment is usually used to explain code.
Sometimes, we may want to 'hide' some code for testing or debugging. This process, called commenting out, is also achieved with comments.
Conclusion
editNow that we've learnt all our operators, we can move on to the next chapter: functions.
Notes
edit- ↑ & and | are valid operators (called bitwise operators, but they are beyond the scope of this book.
Functions
Key concepts:
- Definition of functions
- Blocks
- Function declarations
- Function calls
- Parameters
- Return values
- Naming functions
- Callers and callees
- Functions in variables
Now that we've learnt all our operators, we can get to the next part: functions.
What is a function?
editIn mathematics, a function consists of an input, a process and an output. For example, if x = 3 is input into f(x) = 2x, we get the output 6.
In computers, a function is a collection of statements. When a function is executed, all the statements inside the function will be performed. A function may or may not have inputs, and a function may or may not have outputs. (The latter, of course, cannot be said of spreadsheet functions, which must have outputs.)
How can I declare a function with no inputs and no outputs?
editHere's a simple function with no outputs and no inputs. Look at the code and we'll explain it step by step:
Code | Result |
---|---|
var someNumber:Number = 5;
function addOneToSomeNumber():Void{
someNumber++;
}
|
|
Firstly, the first statement is a simple variable declaration statement we've already learnt before.
The second line has various elements:
function
is added to the beginning of a function declaration just asvar
is added to the beginning of a variable declaration.- addOneToSomeNumber is the name of our function.
- The brackets are for the inputs of the function. Although this function involves no inputs, we still have to add the brackets.
- The
:Void
part is for the output of the function. Normally,Void
would be replaced by the data type of the output. Since this function involves no outputs, we use the keywordVoid
instead. - The opening brace marks the beginning of a block.
A block refers to a group of statements enclosed by a pair of braces. These statements are to be performed in that order. In a function, the block is known as the body of the function. Later, we'll learn other applications of the block. Remember that we always indent the statements in a block. This is automatically done for you in the Flash API.
How can I call a function with no inputs and no outputs?
editIn order to use a function, we need to call it. Let's look at the above example again:
Code | Result |
---|---|
var someNumber:Number = 5;
function addOneToSomeNumber():Void{
someNumber++;
}
addOneToSomeNumber();
trace(someNumber);
|
|
In the function call above, we just called the function addOneToSomeNumber
. The bracket after it is for the inputs of the function, which we'll cover in the next section. The computer performed the function, which involves increasing someNumber by 1. That's how we got the result 6.
How can I declare and call a function with inputs?
editIn programming, the input of a function is called a parameter or argument.[1] Let's modify our addOneToSomeNumber function to accommodate the addition of any number to someNumber:
Code | Result |
---|---|
var someNumber:Number = 5;
function addAnyNumberToSomeNumber(anyNumber:Number):Void{
someNumber += anyNumber;
}
addAnyNumberToSomeNumber(2);
trace(someNumber);
trace(anyNumber);
|
|
In this example, the code anyNumber:Number
is put into the brackets. This is the input of the function and is written as variableName:DataType
.[2] Once input, anyNumber is known as a local variable. This means it cannot be referred to outside the function. That's why we could not trace anyNumber at the end.
Note that this does not result in an error, but the keyword undefined
. Whenever we try to refer to a value that is not defined, Flash will return the value undefined
. We will discuss undefined
and its twin brother null
later.
To call the function addAnyNumberToSomeNumber, we only need to put the value inside the bracket. The data type is not needed!
Now let's modify our code to have two inputs:
Code | Result |
---|---|
var someNumber:Number = 5;
function addTwoNumbersToSomeNumber(firstNumber:Number, secondNumber:Number):Void{
someNumber += firstNumber + secondNumber;
}
addTwoNumbersToSomeNumber(5, 3);
trace(someNumber);
|
|
The comma is used to separate the two parameters. This also works with three parameters or more.
How can I declare and call a function with an output?
editLook at our addAnyNumberToSomeNumber code again. Suppose we don't want to touch the original variable, but want to get the sum of anyNumber and someNumber anyway. That's where a function with a return value comes in handy.
Code | Result |
---|---|
var someNumber:Number = 5;
function addTwoNumbers(originalNumber:Number, anyNumber:Number):Number{
return (originalNumber + anyNumber);
}
trace(addTwoNumbers(someNumber, 7));
|
|
In this function, the value of someNumber was passed on, but instead of changing someNumber, the function returns the sum of someNumber and 7 directly to the trace function.
Note that since this function contains only a return statement and nothing else, it would not make sense to call the function as a separate statement:
Code | Result |
---|---|
var someNumber:Number = 5;
function addTwoNumbers(originalNumber:Number, anyNumber:Number):Number{
return (originalNumber + anyNumber);
}
addTwoNumbers(someNumber, 7);
|
|
See, nothing happens! The function is good for returning a value, but nothing else.
Also note that functions in return values can be used in a variety of versatile ways that is not limited to tracing. For instance, look at the following code:
Code | Result |
---|---|
var someNumber:Number = 5;
function addTwoNumbers(originalNumber:Number, anyNumber:Number):Number{
return (originalNumber + anyNumber);
}
var yetAnotherNumber:Number = 6 / addTwoNumbers(someNumber, 7);
trace(yetAnotherNumber);
|
|
In this script, the computer first evaluates the value addTwoNumbers(someNumber, 7), which equals 12. It then performs the operation 6 / 12, and finally assigns it to yetAnotherNumber.
To conclude, the syntax for declaring a function is as follows:
function functionName(parameter1:DataType1, parameter2:DataType2...):ReturnDataType{ Statements; return value; }
How should I name my functions?
editLike variables, you cannot use reserved words for functions, and the functions can only start with a letter. According to established naming conventions, good function names start with an action verb which can be concatenated with other words using CamelCase. Examples include eatWatermelon(), drinkWater() and smashVase().
What are callers and callees?
editWhen a function is called, it is called a callee. When a function is called by another function, the calling function is called the caller.
The arguments object of a function can find the caller and the callee. The following example traces the caller and callee:
Code | Result |
---|---|
function uselessFunction():Void{
trace(arguments.caller);
trace(arguments.callee);
}
uselessFunction();
|
|
Note that since functions cannot be represented in textual form, the computer traces [type Function], which just indicates that it's a function.
Can I put a function in a variable?
editIf you really want to, you can put a function inside a variable. Here's the syntax:
var variableName:Function = function(parameter1:DataType1, parameter2:DataType2...):ReturnDataType{ Statements; return value; }
Here's an example:
Code | Result |
---|---|
var someFunction:Function = function(someString:String):Void{
trace(someString);
}
someFunction("Hello world!");
|
|
Wait, then what's the deal with the trace function?
editBy now, you may be wondering where you got the trace
function when you've never defined it anywhere. Read the next chapter to find out!
Notes
edit- ↑ Strictly speaking, a parameter refers to the 'field' that is filled out, and an argument refers to the value of a parameter.
- ↑ Like variable declarations, it is not necessary to strong type your variables, but it is a good habit.
Properties and Methods
Key concepts:
- Properties and methods
- Global functions and variables
- The main timeline as a MovieClip
- Dot access
this
,this._parent
with
- Property access with []
- Basic MovieClip methods and properties
- Initialisation with constructors
- Object literals
null
,undefined
Properties and methods are the two components that constitute a class. A property is a variable that belongs to a certain class. A method is a function that belongs to a certain class. This chapter is about this important twosome.
What are top-level functions and global variables?
editActionScript provides a huge number of built-in functions. Some of these functions are methods of built-in classes like MovieClip and Math. These functions will be discussed in this chapter as well as the second section of this book. Other built-in functions do not belong to a built-in class. They can be used whenever you want, wherever you want in your file. Our beloved trace()
is one of these functions. These functions are called top-level functions or global functions.
A global variable is a variable that can be accessed and changed anywhere you want. The _quality
variable is a good example: it affects the quality of the entire SWF. They are provided by Flash.[1]
Breaking news!
editWe interrupt this chapter to bring you some breaking news!
Since you made it to this chapter, it's time to break the news to you: The main timeline (the timeline on which you've been working on all along) is a MovieClip instance.
What does this imply?
All objects have properties and methods, remember? Therefore, the main timeline has various built-in properties and methods we have to learn. We will learn some of them in this chapter, and save the rest for the next section.
Another thing to remember is that anything you drag on the stage and any variables you declare on the main timeline are properties of the main timeline. The reason why new properties can be added to the instance is because MovieClip is a dynamic class. We will talk about dynamic classes in the third section.
How can I access the property of another object?
editThe most common way to access the property of another object is as follows:
objectName.propertyName
Note that in order for this to work, we have to ensure that propertytName is a property of what we're working on.
Let's try this out. Open Flash. Create a new MovieClip in the library. Draw an apple in it and drag it anywhere onto the stage. Give it the instance name of 'apple'.[2] Now click on the apple again. on the first frame, type in var juiciness:Number = 5
. (Recall: all variables you declare in a timeline is a property of that MovieClip.) Type in the following code:
Code | Result |
---|---|
trace(apple.juiciness);
|
|
In this code, we have traced the juiciness property of the apple using the dot operator.
What are this
and _parent
?
edit
this
is used to address the current location. For example, if you're in the Main Timeline, this.crunchiness will return the crunchiness of the main timeline. Let's try out our apple example again with this
.
Code | Result |
---|---|
trace(this.apple.juiciness);
|
|
This does the same thing, except it explicitly states that apple is a property of the current object (the main timeline). As you can see, this
is not always necessary.
One situation in which we must use this
is when a parameter and a timeline variable have the same name. In this case, one must put this
before the timeline variable so that the computer knows you're not talking about the local variable. Here's an example:
Code | Result |
---|---|
var someString:String = "random text";
function stringTogether(someString:String):String{
return (someString + " " + this.someString);
}
trace(stringTogether("even randomer text"));
|
|
In this example, return (someString + " " + this.someString);
concatenates the local variable someString, a space character and a timeline variable someString together.
So far, we've only been referencing the apple from the main timeline. Is it possible to reference the main timeline from the apple? The answer: yes, and it involves _parent
.
Open the Flash file with the apple again and type in the following code:
Code | Result |
---|---|
In the first frame of the main timeline: var crunchiness:Number = 7;
In the first frame of the apple symbol: trace(this._parent.crunchiness);
|
|
In this example, the apple is contained in the main timeline, so the main timeline is the apple's 'parent'. Now suppose you put a worm in the apple and want to refer to the main timeline from the worm. No problem: you can put in as many layers of _parent
as necessary:
Code | Result |
---|---|
In the first frame of the main timeline: var crunchiness:Number = 7;
In the first frame of the worm symbol: trace(this._parent._parent.crunchiness);
|
|
The worm's parent is the apple and the apple's parent is the main timeline. Works like magic!
What's with with
?
edit
Now suppose the worm goes on a quest to reduce the crunchiness and sweetness of the main timeline and the juiciness of the apple. We can do this:
Code | Result |
---|---|
In the first frame of the main timeline: var crunchiness:Number = 7;
var sweetness:Number = 4;
In the first frame of the apple symbol: var juiciness:Number = 6;
In the first frame of the worm symbol: this._parent._parent.crunchiness--;
this._parent._parent.sweetness--;
this._parent.juiciness--;
trace(this._parent._parent.crunchiness);
trace(this._parent._parent.sweetness);
trace(this._parent.juiciness);
|
|
Now suppose we're too lazy to type in 'this._parent' so many times. We can use with
to solve this problem:
Code | Result |
---|---|
In the first frame of the main timeline: var crunchiness:Number = 7;
var sweetness:Number = 4;
In the first frame of the apple symbol: var juiciness:Number = 6;
In the first frame of the worm symbol: with(this._parent){
_parent.crunchiness--;
_parent.sweetness--;
juiciness--;
}
trace(this._parent._parent.crunchiness);
trace(this._parent._parent.sweetness);
trace(this._parent.juiciness);
|
|
That saves us from having to type in this._parent three times. All the computer has to interpret your code is to append this._parent in front of each statement in the block.
What if I want to treat the property name as a string?
editSometimes, we need to treat a property name as a string so that we can concatenate several strings to form the property name. Here's an example:
Code | Result |
---|---|
var currentAnimal:String = "cat";
var dogFood:String = "biscuits";
var catFood:String = "fish";
var fishFood:String = "smallerFish";
trace(this[currentAnimal + "Food"])
|
|
In this example, we concatenated currentAnimal ('cat') and 'food' to form the property name catFood, returning the string 'fish'.[3]
How can I access an object's properties through a variable?
editIn the second chapter, we've learnt that by assigning anything other than a primitive data type to a variable, we are putting a link to that object inside the variable. We can also access an object's properties with a variable:
Code | Result |
---|---|
In the first frame of the main timeline: var someFruit:MovieClip = apple;
trace(apple.juiciness);
trace(apple["juiciness"]);
In the first frame of the apple symbol: var juiciness:Number = 6;
|
|
What are some MovieClip properties and methods that I must know?
editThe following are some MovieClip properties that will be used throughout the rest of the section.[4]
- _x and _y (both numbers) indicate the position of a MovieClip relative to its parent. Remember that in ActionScript, the higher the value of _y, the lower the position of the MovieClip. The origin (0,0) is located on the top-left corner. This may be counter-intuitive if you are familiar with Cartesian planes.
- _width and _height (both numbers) indicate width (horizontal) and height (vertical) dimension of a MovieClip respectively.
- _visible indicates whether the MovieClip is visible. If _visible is true, the MovieClip is visible and vice versa.
- _currentframe indicates which frame the MovieClip is currently on.
_x, _y, _width, _height and _visible can all be changed by assigning a different value to them. Open the Flash file with the apple again and type in the following code:
apple._x = 100;
apple._y = 200;
apple._width = 100;
apple._height = 100;
You should find noticeable changes in the position and dimensions of the apple (unless, of course, your apple happened to have exactly the same position and dimensions on the stage!)
Unlike the others, _currentframe cannot be changed with assignment statements. Instead, several functions are used to manipulate the current frame:
play()
andstop()
will play and stop playing the frames in order respectively. The default is to play, so whenever you want to stop at a frame, you should add thestop()
code. For example, if you put nothing on the first five frames, thenstop()
on the sixth, Flash will play until the sixth frame.gotoAndPlay(frame)
andgotoAndStop(frame)
will go to the specified frame, then play and stop the Flash respectively. If there is astop()
statement on the target frame of gotoAndPlay, Flash will stop, and if there is aplay()
statement on the target frame of gotoAndStop, Flash will also stop.prevFrame()
andnextFrame()
go to the previous and next frame respectively. Unless there is astop()
statement on the target frame, they will play.
More properties and methods will be introduced in the second section.
How can I call a method of another object?
editCalling a method of another function is just as easy as accessing their variables. Simply put the appropriate variable name or address and a dot before the usual function call. Let's say we have a second frame on our apple MovieClip with a half-eaten apple.
Code | Result |
---|---|
In the first frame of the main timeline: apple.nextFrame();
In the first frame of the apple symbol (a complete apple complete with a worm): stop();
trace("First frame!");
In the second frame of the apple symbol (a half-eaten apple): stop();
trace("Second frame!");
|
|
In this example, the worm symbol traces 'First frame!' when it is initialised, but the main timeline will quickly make the apple symbol go to the second frame.
What is a constructor?
editA constructor function is the most important method of a class. It is used to initialise an instance of a class. Remember the syntax for initialisation that we learnt in the first chapter? Although it worked perfectly for the primitive data types, it is more complicated for the composite data types (which you can't type in directly).
We won't learnt how to make our own constructor functions until the third chapter. For now, let's stick to calling constructor functions. The syntax for calling a constructor function is as follows:[5]
var variableName:DataType = new DataType(parameter1, parameter2);
For instance, let's say there's a Dog class and we want to make a new Dog instance. If there are two parameters, species and colour, in the constructor, we should write the following code:
Code | Result |
---|---|
//Assume there is a Dog class.
var spot:Dog = new Dog("chihuahua", "black");
trace(Dog.species);
trace(Dog.colour);
|
|
This creates a new spot instance of the Dog class with the species 'chihuahua' and the colour 'black'.
The primitive data types can also be applied the constructor function when they are initialised. This will be covered in the second section.
It is possible to use a constructor class outside of variable declaration/assignment statements. This will create an instance without a warm and cozy variable home.
Code | Result |
---|---|
trace(new Number());
|
|
When don't I need a constructor?
editFirstly, primitive data types don't usually need constructors since they can be initialised with their literals. For example, var someString:String = "Wikibooks" will do, and you don't have to write someString:String = new String("Wikibooks").[6]
We don't need to use the constructor function on the Object class, either. (Remember the Object class? It is the grand-daddy of all classes.) Instead, it can be generated like this:[7]
var variableName:Object = {property1:value1, property2:value2, ..., method1:function1, method2:function2 ...};
The function1, function2, etc., should be replaced with the syntax for putting a function inside a variable (which we've met in the functions chapter). Look at this example:
Code | Result |
---|---|
var someObject:Object = {
crunchiness:7,
juiciness:5,
eat:function(){
trace("Mmmm! It's " + this.crunchiness + " on the crunchiness scale and "
+ this.juiciness + " on the juiciness scale.");
}
};
trace(someObject.crunchiness);
someObject.eat();
|
|
A new object is created with 7 as its crunchiness and 5 as its juiciness.
What are null
and undefined
?
edit
In computer science if a value is null or undefined, there isn't anything in it. For example, the key field in a database table must be unique and non-null, which means it can't be empty. In ActionScript, null
and undefined
are two flexible, all-purpose values that can be put into variables of any type. A variable which is not yet defined (i.e. you haven't assigned any value to it and haven't called its constructor) is automatically set to undefined. Null and undefined are considered equivalent values with the normal equality operator (i.e. null == undefined
returns true
), but not the strict equality operator (i.e. null === undefined
returns false
). Consider the following example:
Code | Result |
---|---|
var someNumber:Number;
trace(someNumber);
someNumber = null;
trace(someNumber);
var someString:String = undefined;
trace(undefined == null);
trace(undefined === null);
|
|
In this example, someNumber is at first undefined
, then set to null
. Next, someString is set to undefined
. (That is just to show that undefined can be fit into any data type.) Finally, it is found that undefined is equal, but not strictly equal, to null.
One should be more careful when using the ! operator with null
and undefined
.
Code | Result |
---|---|
var someBoolean:Boolean;
trace(!someBoolean);
var someNumber:Number;
trace(!someNumber);
|
|
In the first trace, someBoolean was undefined. !someBoolean means 'someBoolean is not true', which is different from saying 'someBoolean is false'. Since someBoolean was undefined, it was 'not true' (but not false either), so !someBoolean is true. Also note that a number can be used with the ! operator when it's undefined, as shown in the second trace statement.
Notes
edit- ↑ It is also possible to define your own global variables like this: _global.variableName = value; Notice that global variables are not strong typed. Defining your own global variables is a deprecated practice and should be used sparingly.
- ↑ You can change the instance name of any MovieClip in the Properties panel.
- ↑ In fact, there is more to this syntax than meets the eye, but let's keep up the suspense until the third section.
- ↑ In ActionScript 3.0, all the leading underscores have been abolished.
- ↑ Instances of the MovieClip and TextField classes are created with special methods. We'll discuss them in the second section.
- ↑ There is a subtle difference between these two. "Wikibooks" is just a primitive string literal, while new String("Wikibooks") is an object of the String wrapper class. We will learn more about this in the second section.
- ↑ Note that the parts enclosed in braces are also considered a literal of the object.
Control Statements
Key concepts:
- Control statements
- Select statements and conditions
- Switch statements
default
,break;
- For loops
- Arrays
while
anddo ... while
loopsfor ... in
loops- Using
arguments
with conditions and loops
Sometimes, we need to do a certain action many times. Sometimes, we don't want to perform an action in certain situations, but want to in others. This chapter is about control statements, which control how statements are executed.
What are selection statements?
editA selection statement, also known as a conditional statement, is a type of control statement that allows you to perform one action if a value is true, and another action if a value is false. The Boolean value that determines which action will be taken is called the condition.
How can I use if
?
edit
Consider the following example:
Code | Result |
---|---|
var isHappy:Boolean = true;
if(isHappy){
trace("I am happy!");
}
|
|
In the above code, the words 'I am happy!' is traced if isHappy
is true. What if we wanted to trace 'I am unhappy.' if isHappy
is not true?
Code | Result |
---|---|
function traceMood():Void{
if(isHappy){
trace("I am happy!");
} else {
trace("I am unhappy.");
}
}
var isHappy:Boolean = true;
traceMood();
isHappy = false
traceMood();
|
|
In the above code, we used else
to trace the words 'I am unhappy.' if isHappy
is false or null. If the <Now suppose we want to trace 'Meh.' when we're neither happy nor unhappy. Here's the code for that:
Code | Result |
---|---|
function traceMood():Void{
if(isHappy){
trace("I am happy!");
} else if (isHappy == false){
trace("I am unhappy.");
} else {
trace("Meh.");
}
}
var isHappy:Boolean;
traceMood();
|
|
In the above code, the computer first determined whether isHappy was true. Since it wasn't, it went on to the second part. Figuring out that isHappy was neither true or false, it went on to trace 'Meh'. Note that one cannot use the ! operator here because !isHappy simply means 'isHappy is not true', which is different from 'isHappy is false'.
To conclude, the syntax for selection statements is:
if(condition){ Statements if the first condition is true; } else if(condition){ Statements if the second condition is true; } ... ... else { Statements if none of the conditions is true; }
Callers and callees[check spelling] are often used with selection statements. Here's an example showing the use of callers with a selection statement:
Code | Result |
---|---|
function someCallee(){
if(arguments.caller == someCaller){
someNumber++;
trace("No, *I* get to say that Hello World line!");
arguments.caller();
}
}
function someCaller(){
trace("Hello world!");
if(someNumber == 5){
someCallee();
}
}
var someNumber:Number = 5;
someCaller();
someCallee();
|
|
In this example, someCaller is called and traces 'Hello world!'. Since someNumber is 5, it calls someCallee. someCallee increases someNumber, traces the jealous line, then calls someCaller again. someCaller then annoys someCallee by tracing 'Hello world!' again. However, since someNumber is now 6, it does not trace someCallee again. The last line does nothing as someCallee only works when the caller is someCaller. This technique can avoid the accidental calling of functions outside the intended area.
Do not attempt to remove the selection in someCaller! If you do so, it will be like having two mirrors facing each other, resulting in an infinite loop. We will discuss infinite loops later in this chapter.
What are switch
statements?
edit
Sometimes, we have several conditions and it would be infeasible to make an if
statement for every single one of them. In this case, we may use a switch
statement. The syntax is as follows:
switch(variable){ case value: Statements in this case; break; ... default: Statements if none of the cases are satisfied; }
Look at the following example for an illustration of what is happening:
Code | Result |
---|---|
var today:Number = 5;
switch(today){
case 1:
trace("Monday");
break;
case 2:
trace("Tuesday");
break;
case 3:
trace("Wednesday");
break;
case 4:
trace("Thursday");
break;
case 5:
trace("Friday");
break;
case 6:
trace("Saturday");
break;
case 7:
trace("Sunday");
break;
default:
trace("That's not a valid day.");
}
|
|
The computer detects that today = 5 and traces the corresponding string, Friday. If the day were 0 or 8 or anything that isn't 1-7, Flash will execute the default action, i.e. trace 'That's not a valid day.'.
Note that the break;
statement tells the computer to break out of the switch statement. If the break;
statements are not included, the computer will continue executing the statements of the cases below it. For example:
Code | Result |
---|---|
var today:Number = 5;
switch(today){
case 1:
trace("Monday");
case 2:
trace("Tuesday");
case 3:
trace("Wednesday");
case 4:
trace("Thursday");
case 5:
trace("Friday");
case 6:
trace("Saturday");
case 7:
trace("Sunday");
}
|
|
What are loops?
editSometimes, we need to perform an action many times. This is where loops come in handy.
How do I use a for
loop?
edit
A for loop has a variable called a loop counter that changes constantly. When the loop counter no longer meets a certain condition, the loop will stop. The syntax of a for loop is as follows:
for(declaration and initialisation of the counter; condition; change in the counter){ Statement to be repeated; }
For example:
Code | Result |
---|---|
for(var i:Number = 0; i < 10; i += 2){
trace("Wikibooks is awesome.");
}
|
|
The following steps were involved:
- i is set to zero.
- The computer traces the sentence since 0 < 10 is true. i increases by 2 and becomes 2.
- The computer traces the sentence since 2 < 10 is true. i increases by 2 and becomes 4.
- The computer traces the sentence since 4 < 10 is true. i increases by 2 and becomes 6.
- The computer traces the sentence since 6 < 10 is true. i increases by 2 and becomes 8.
- The computer traces the sentence since 8 < 10 is true. i increases by 2 and becomes 10.
- The computer breaks the loop since 10 < 10 is false.
Like with switch statements, it is possible to break the loop with a break;
statement:
Code | Result |
---|---|
var someVariable:Number = 3;
for(var i:Number = 0; i < 5; i ++){
trace("Wikibooks is awesome.");
someVariable ++;
if(someVariable > 5){
break;
}
}
|
|
In this example, the loop was broken before i could equal 5 because the selection statement broke the loop.
Sometimes, we only want to stop the iteration of the loop, and not the entire loop. We use the continue statement for this:
Code | Result |
---|---|
var someVariable:Number = 3;
for(var i:Number = 0; i < 10; i ++){
trace("someVariable:" + someVariable);
if(someVariable >= 5){
continue;
}
someVariable++;
}
|
|
In this example, someVariable only increases if it is lower than 5.
When creating loops, one must be very careful not to create infinite loops. Infinite loops crash applications (warning: do not try this at home):
Code | Result |
---|---|
var someVariable:Number = 3;
for(var i:Number = 0; i > -1; i ++){
trace("Wikibooks is awesome.");
someVariable ++;
if(someVariable > 5){
break;
}
}
|
|
What are arrays?
editAn array is an object the contains, well, an array of objects. It can store practically any object from numbers, Boolean values and strings to MovieClips, TextFields and sounds. These objects are called array elements. There are several ways to use the array's constructor function. In this chapter, we will only use the one without parameters.
Code | Result |
---|---|
var months:Array = new Array();
months[0] = "January";
months[1] = "February";
months[2] = "March";
...
months[11] = "December";
trace(months[0]);
|
|
The position of an array element is called its index. Indices start with 0, not 1. We can access an array element using the syntax arrayName[index]
. In the example, we didn't put in any parameters into the months. The computer only initialises a blank array.[1] Note that it is not optional to call the array's constructor function as you can't assign any elements to an undefined variable.
We will learn to manipulate arrays in the second section. For now, let's focus on using loops with arrays. The following example shows how to use for loops with arrays:
Code | Result |
---|---|
var dogs:Array = new Array();
dogs[0] = "Spot";
dogs[1] = "Lucky";
dogs[2] = "Max";
...
dogs[9] = "Rover";
for(var i:Number = 0; i < dogs.length; i++){
dogs[i] = dogs[i] + "is a good dog.";
trace(dogs[i]);
}
|
|
The above loop adds the string 'is a good dog.' to the end of each element and traces it. Note that the length property of an array is the number of elements in it, or 9 in this case.
What is the arguments object?
editIn the chapter about functions and earlier in this chapter, we briefly examined the arguments object. Let's go back to it.
arguments is actually a funny type of array. It contains all the arguments passed on to the function (note that this may be different from the number of parameters declared). Look at the following example:
Code | Result |
---|---|
function grabStrings(string1:String, string2:String, string3:String, string4:String):Void{
trace(arguments.length);
trace(arguments[0]);
}
grabStrings("foo", "bar", "baz");
|
|
In this example, we first traced the length of the arguments object, which is 3 (there being three arguments passed: foo, bar and baz). We then traced the first argument, 'foo'. Now let's use a loop with it:
Code | Result |
---|---|
function traceStrings(string1:String, string2:String, string3:String, string4:String):Void{
for(var i:Number = 0; i < arguments.length; i++){
trace(arguments[i]);
}
}
traceStrings("foo", "bar", "baz");
|
|
In the above example, we don't need to worry about tracing 'undefined' because the loop only lasts for the length of the arguments object.
What are while
and do ... while
loops??
edit
while loops allow us to specify a condition without using a counter. The syntax is:
while(condition){ Statements if the condition is true; }
Code | Result |
---|---|
var months:Array = new Array();
months[0] = "January";
months[1] = "February";
months[2] = "March";
...
months[10] = "December";
var i:Number = 0;
while(months[i].substring(months[i].length - 4, months[i].length) == "uary" ){
trace(months[i++]);
}
|
|
You don't have to understand how the condition works yet. Just take for granted that it returns true
if the month ends in 'uary'. In this script, the computer will keep tracing the month until it reaches a month that doesn't end in 'uary', or 'March' in our example.
It is even easier to fall into the trap of infinite loops with while loops. Try to avoid them!
do ... while loops are similar except it ensures that it will always perform the action on the first time. For example:
Code | Result |
---|---|
var days:Array = new Array();
days[0] = "Monday";
days[1] = "Tuesday";
days[2] = "Wednesday";
days[10] = "Sunday";
var i:Number = 0;
do{
trace(days[i++]);
} while(days[i].length > 6 );
|
|
In this example, the first element, Monday, gets traced, even though it is exactly six letters long. The loop stops at Friday, which is also exactly six letters long but isn't invited to the club as it isn't the first element.
How do I use a for ... in
loop?
edit
Apart from for loops, there's another type of loop called for ... in loops. It loops through all the 'loopable' properties of a class. For arrays, this refers to all the elements. Whether a variable is 'loopable' depends on its visibility, which we'll cover in the third section. The syntax is as follows:
for(Declaration of the counter without initialisation in Target object) { Statements to be executed; }
The target object can be any composite data type. Let's rewrite the dog loop as a for ... in loop:
Code | Result |
---|---|
var dogs:Array = new Array();
dogs[0] = "Spot";
dogs[1] = "Lucky";
dogs[2] = "Max";
...
dogs[9] = "Rover";
for(var i:String in dogs){
dogs[i] = dogs[i] + "is a good dog.";
trace(dogs[i]);
}
|
|
In the above, the computer loops through all the elements of dogs, adds 'is a good dog.' at the end, and traces. Note that although i is a string, Flash automatically converts it into the index.
Now let's try again with an Object
instance.
Code | Result |
---|---|
var spot:Object = {species:"chihuahua", colour:"brown"}
for(var i:String in spot){
trace(spot[i]);
}
|
|
In this case, Flash looped through both visible properties of spot (species and colour) and returned their values.
Conclusion
editSo far, we've gone through five chapters. In every case, you, the programmer, are the only person to input into the application. However, the purpose of ActionScript is to create an interactive application where the end user can also input into the system. In the next chapter, we will cover the most important way to do this: through event handling.
Notes
edit- ↑ Because of the existence of a global function Array(), you don't have to put the 'new' before Array() if you don't want to.
Event Handling
Key concepts:
- Events
- Event handlers
- Event handler declarations
- Key and Mouse classes
- Listeners
- Polling
An event is an unpredictable event; you never know when it will happen, although you do know how to respond to it. Many events are based on the input devices of the end user's computer, such as mouse clicks. Others may be concerning objects in the application. In this section, we'll learn how to deal with events.
What are event handlers?
editAn event handler is a function that shows what to do when an event occurs.[1] It is declared as follows:
objectName.eventHandlerName = function(){ Statements to execute when the event occurs; }
Code | Result |
---|---|
//Assume there's a MovieClip with the instance name 'apple' on the stage.
apple.onPress = function(){
trace("That's one tasty apple, all right!");
}
|
|
Each class has its own events. Examples of events in the MovieClip class include onPress (when the mouse button is pressed while the cursor is above the MovieClip), onRelease (when the MovieClip is released while the cursor is above the MovieClip), onLoad (when the MovieClip is loaded), and so on. We will go into detail about these in the MovieClip chapter.
What are the Key and Mouse classes?
editThe Key and Mouse classes are classes that contain only events, static methods and static properties. You cannot create instances of the two classes. (Static methods and properties will be covered briefly in the next chapter and in detail in the third section). The Key and Mouse classes contain a lot of event handlers which are, surprisingly enough, related to the keyboard and mouse respectively. For the rest of this chapter, we'll be using the following event handlers:
- Mouse.onMouseDown (when the left mouse button is pressed)
- Key.onKeyDown (when any key is pressed)
What are listeners?
editSince we can't create instances of the mouse and key classes, how the heck are we supposed to use the useful events inside? The answer: listeners.
Let's say we want an apple instance to shrink whenever the mouse is pressed anywhere on the stage. Here's the code for it:
Code | Result |
---|---|
//Assume there's a MovieClip with the instance name 'apple' on the stage.
Mouse.addListener(apple);
apple.onMouseDown = function(){
this._width -= 2;
this._height -= 2;
}
|
|
In this example, apple is added to the Mouse class's list of listeners. When the mouse is pressed anywhere on the stage, a notification is sent to the apple to shrink it.
The strategy of using listeners is called callback notification.
What is polling?
editPolling refers to the computer checking repetitively to see if an event has occurred. In a way, event handling is also polling, although this polling strategy is built into ActionScript. There's also a way to poll by yourself. This strategy, which serves as an alternative to event handling, will be covered in our detailed discussion of the Key class later on.
Conclusion
editSince we've now learnt all the basics of ActionScript, we can now look at each of the built-in classes up close and personal, and learn how to use each of them to create powerful and dynamic Flash applications.
Notes
edit- ↑ Technically, an event handler is a property which contains a function.
Primitive Data Types
Key concepts:
- Wrapper classes
- Literals of primitive data types vs. instances of wrapper classes
- instanceof and typeof
- Character indices
- Substrings
- Other String methods
- Scientific notation and hexadecimals
- Infinity, maximum and minimum values, and NaN
- More about conversion
- Static properties and methods
- Constant variables
After cramming all those basic concepts in your head, you deserve a break! This chapter is all about primitive data types.
What is a wrapper class?
editA wrapper is a class that 'wraps' the three primitive data types with properties and methods. There are, unsurprisingly, three wrapper classes, each corresponding to a primitive data type:
- Number
- String
- Boolean
Each class has a constructor function which can be used to initialise it. Initialising a number, string or Boolean value with its constructor but without any arguments will return a blank value, i.e. zero, an empty string and an empty Boolean value respectively:
Code | Result |
---|---|
trace(new Number());
trace(new String());
trace(new Boolean());
|
|
Although traced as true, new Boolean() is neither true nor false.
You can also put the literal into the first parameter:
Code | Result |
---|---|
trace(new String("Hello world!"));
trace(new Number(123));
trace(new Boolean(true));
|
|
There's a slight difference between a 'string' and a 'string object'. Look at the following example:
Code | Result |
---|---|
trace(123 instanceof Number);
trace(new Number(123) instanceof Number);
trace(typeof 123);
trace(typeof new Number(123));
|
|
instanceof and typeof are special operators. instanceof returns true if the left operand is an instance of the right operand. In this example, 123 is not an instance of Number, but new Number(123) is. typeof returns the data type of the right operand, which can be string, number, boolean, function, movieclip or object (for non-MovieClip objects). The lowercase letters are intentional because this is what typeof returns. In our example, 123 is of the primitive data type number, but new Number(123) is an instance of the Number wrapper class.
Flash converts an instance of the wrapper class into the primitive data and vice versa whenever it is necessary. If we want to manually convert an instance of a wrapper class into a primitive data type, we can use the valueOf() function:
Code | Result |
---|---|
trace(new Number(123).valueOf() instanceof Number);
|
|
To convert the other way, simple call the constructor function.
How can I manipulate strings?
editThe only string property you need to know is the length property, which shows the number of characters in the string. For example:
Code | Result |
---|---|
trace("Hello world!".length);
|
|
Note that the space is counted.
Another thing you need to know is that the position of a character in a string is called its index. If the index is a positive number, it is counted from the first character, and if the index is a negative number, it is counter from the last character. The first character is defined as 0 and the last character is defined as -1. For example, the index of 'p' in 'spot' is 1 or -3 and 'o' is 2 or -2. Now let's start manipulating strings!
How can I locate a character in a string?
editThe following functions are related to characters in ActionScript:
- String.fromCharCode(code point 1, code point 2...)
- string.charAt(index of the character);
- string.charCodeAt(index of the character);
fromCharCode returns a string using the Unicode code points specified in the parameters. Note that we wrote 'String.fromCharCode'. That's exactly the way you're supposed to type it! This is because fromCharCode is a static method, which means it belongs to the whole class, and not just a specific string.
charAt returns a character at the desired position, while charCodeAt returns the Unicode code point of the desired character.
For example:
Code | Result |
---|---|
trace(String.fromCharCode(62, 56, 123));
trace("Hello world!".charAt(4));
trace("Hello world!".charCodeAt(4));
|
|
Remember, ActionScript uses Unicode code points, not ASCII ones, for string manipulation. ASCII code points will come in handy later.
What is a substring?
editA substring is a string inside another string. There are three ways to find a substring when we know its position in a string:
- string.substr(index of the first character, length);
- string.substring(index of the first character[, index of the last character]);
- string.slice(index of the first character[, index of the last character]);
If you are familiar with SQL or spreadsheets, you may have noticed find that these two functions are quite different from functions like SUBSTRING()/SUBSTR()/MID() in SQL or spreadsheets as the string is not specified in the first parameter because it is the string that contains the method in the first place.
Note that the last character is excluded from the substring in substring() and slice(). If the index of the last character is not specified, Flash will return everything till the end. Here's an example with all three functions:
Code | Result |
---|---|
trace("Hello world!".substr(4, 5));
trace("Hello world!".slice(4, 9));
trace("Hello world!".substring(4, 9));
trace("Hello world!".slice(4));
trace("Hello world!".substring(4));
|
|
Sometimes, we need to find the position of a known substring inside a string. Then we need these two functions:
- string.indexOf(substring[, index of the first character]);
- string.lastIndexOf(substring[, index of the last character]);
indexOf is very similar to FIND() in spreadsheets. It looks for the substring in the string starting from the character specified in the second parameter. If the second parameter is left blank, it starts from the beginning. The position of the first character of the first occurrence of the substring is returned. lastIndexOf is pretty much the same except it returns the last occurrence, not the first, and you specify when to stop looking, not where to start looking. The search is case-sensitive. If no occurrence is found, Flash returns -1. Example:
Code | Result |
---|---|
trace("Tralalalala".indexOf("la", 4));
trace("Tralalalala".indexOf("la"));
trace("Tralalalala".lastIndexOf("la", 8));
trace("Tralalalala".lastIndexOf("la"));
trace("Tralalalala".lastIndexOf("lah"));
|
|
What are some other String methods?
edit- toString(subject of conversion) is an alternative way to convert something to a string. It's pretty much the same as String(subject of conversion), which we've met back in Chapter 1.
- concat(string1, string2...) also does pretty much the same thing as the text concatenation operator.
- string.toUpperCase and string.toLowerCase converts the specified string to upper- and lowercase respectively. Surprising, eh?
- string.split(delimiter, number of elements) will be covered in the next chapter.
How can I start a new line?
editnewline
is a string literal that can help you start a new line. It is not enclosed with quotation marks; instead, it is concatenated with other strings.
Code | Result |
---|---|
trace("Hello!" + newline + "World!");
|
|
How can I express a number in other notation systems?
editActionScript represents numbers in scientific notation in a way that is quite similar to calculators. The letter 'e' is added between the 10x portion and the number. You don't have to ensure that the first number is between 1 and 10, or add a positive (+) sign before the exponent, as Flash automatically does that for you. Flash also converts numbers to and from scientific notation when it see fits:
Code | Result |
---|---|
trace(123e15);
trace(1.23e-2);
trace(10000000000000000000000000000000000);
|
|
To express a number o hexadecimals, simply type in '0x' before the hexadecimal. Flash will convert it into denary for you:
Code | Result |
---|---|
trace(0x12A);
|
|
Hexadecimals will be very useful when we deal with colours later.
What are some special numbers?
editApart from the usual floating-point decimals and integers we manipulate, ActionScript has five special numbers, all static properties of Number:
- Number.NEGATIVE_INFINITY
- Number.POSITIVE_INFINITY
- Number.MAX_VALUE
- Number.MIN_VALUE
- Number.NaN
Like a static method, a static property is a property that belongs to the whole class, not a single instance. They are also accessed using the class name rather than the instance name. Note that these numbers are in all caps and separated by underscores (_). This is because they are constants. Although constants are variables, they are not supposed to be changed; they're just there because it would be infeasible to use literals every time.
The literals of Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY and Number.NaN are -Infinity, Infinity and NaN respectively.
Number.MAX_VALUE and Number.MIN_VALUE are the largest integral value and smallest decimal value in Flash respectively. Number.NEGATIVE_INFINITY and Number.POSITIVE_INFINITY represent, well, negative and positive infinity respectively. Number.NaN means 'not a number'. You've probably got this value before, when you tried to treat non-numbers as numbers, such as the following:
Code | Result |
---|---|
trace(123 - "Hello world!");
|
|
Remember that infinity is always infinity, no matter how much you subtract from it or into how many pieces you divide it. Also remember that dividing by zero does not result in undefined or NaN, but infinity.
Code | Result |
---|---|
trace(Number.POSITIVE_INFINITY / Number.MAX_VALUE);
trace(Number.POSITIVE_INFINITY - Number.MAX_VALUE);
trace(12 / 0);
|
|
Two global functions, isFinite(number) and isNaN(number), can help you decide whether a number is inFinite and NaN respectively. isFinite returns true if the number is finite and false if it isn't; isNaN returns false if the parameter is a legitimate number and otherwise returns true.
Code | Result |
---|---|
trace(isFinite(Infinity));
trace(isFinite(-Infinity));
trace(isFinite(12/0));
trace(isFinite(Number.MAX_VALUE));
trace(isNaN(45 * "Hello world!"));
trace(isNaN("Hello world!"));
trace(isNaN(-12/0));
|
|
Note that the last one is true because "Hello world!" is not a number (but a string). We will go into even more detail in the Math class chapter.
A word on conversion
editBack in the first chapter, we learnt to convert between the primitive data types. Let's take another look at each conversion process.
Let's start with String(value). If we attempt to convert a MovieClip or TextField, it will be converted into the form 'leveln_instanceName', e.g. level0_someMovieClip refers to a MovieClip on the main timeline. If we attempt to convert an array, the resulting string will contain all the elements separated by a comma. If we attempt to convert any other object, we will get [object Object], and if we attempt to convert a function, we get [type Function].
Code | Result |
---|---|
//Assume that someMovieClip is a MovieClip on the stage.
trace(String(new Array(12, 32, 34)));
trace(String(someMovieClip));
trace(String(new Sound));
trace(String(someFunction));
function someFunction():Void{
return;
}
|
|
If we put anything other than true, false or a numeral-only string into Number(value), we would get NaN.
If we put anything other than 0 or 1 into Boolean(value), we would get false if that anything is null or undefined, and true otherwise.
Another way to convert a string into an integer is to use the parseInt global function. The first parameter is a string, and the second, optional parameter is the base of the numeral system.
Code | Result |
---|---|
trace(parseInt("13.6"));
trace(parseInt("0x14"));
trace(parseInt("1.23e-3"));
trace(parseInt("001101", 2));
|
|
Note that we don't need a second parameter for the second trace because 0x already implies that the base is 16.
Conclusion
editNow that we've learnt all about primitive data types, we will learn how to manipulate arrays.
Notes
edit
Arrays
Key concepts:
- Indexed arrays vs. associative arrays
- The Array constructor and array literals
- Nested arrays
- Array concatenation
- Adding and removing elements from an array
- Popping, pushing, shifting and unshifting
- Splicing
- Extracting array elements by slicing
- Inter-conversion between arrays and strings
- Array sorting
- Sorting numbers and strings
- Custom criteria
- Returning indices
- Sorting on fields
- Reversing arrays
We've learnt about arrays back in the control statements chapter. However, we didn't learn how we can manipulate them. That's our focus in this chapter.
What is the nature of the Array class?
editIn computer programming, there are actually two kinds of arrays, indexed arrays and associative arrays (also known as hashes). In indexed arrays, each array element has an index, whereas in associative arrays, each array element has a name. In ActionScript, the Array class produces indexed arrays, while the Object class produces associative arrays.
In the chapter about control statements, we've covered the use of Array class's constructor function without parameters, and we won't go through it again in this chapter. In this chapter, we will go through two more ways to use the constructor function, as well as the array literal. (Yes, arrays have literals too!)
Code | Result |
---|---|
var dogs:Array = new Array(10);
dogs[0] = "Spot";
dogs[1] = "Lucky";
dogs[2] = "Max";
...
dogs[9] = "Rover";
trace(dogs[0]);
var fruits:Array = new Array("Apples", "Bananas", "Oranges", "Pears");
trace (fruits[2]);
var months:Array = ["J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D"];
trace(months[9]);
|
|
In the first example, we initialised the dogs array by specifying its length, then assigned a string value to each of the elements. In the second example, we put in the values directly into the constructor function.[1] In the third example, we used the array literal. The array literal is always surrounded by a pair of square brackets, and each element is separated by a comma, like this: [1,1,3,5,8,13,21,34].
What is a multidimensional array?
editA multidimensional array, or a nested array, is an array that contains arrays as elements. It can represent data in a tabular form. For instance:
Code | Result |
---|---|
var multiplicationTables:Array = new Array(10);
for(var i:Number = 0; i < multiplicationTables.length; i++){
multiplicationTables[i] = new Array(10);
for(var j:Number = 0; j < multiplicationTables[i].length; j++){
multiplicationTables[i][j] = i * j;
}
trace(multiplicationTables[i]);
}
|
|
Once we've learnt about dynamic MovieClip and TextField creation as well as the drawing API, we can actually present this array as a table.
Fortunately for us, there's a shortcut to creating nested arrays: using the array literal:
Code | Result |
---|---|
var someNestedArray:Array = new Array([1, 3, 5, 7, 9], [1, 1, 2, 3, 5], [2, 4, 6, 8, 10]);
trace(someNestedArray[0]);
trace(someNestedArray[1]);
trace(someNestedArray[2]);
trace(someNestedArray);
|
|
Note, in the last trace, that the multidimensional array is 'flattened' when it is turned into a string and traced. We can use the split method to create a really flattened array:
Code | Result |
---|---|
var someNestedArray:Array = new Array([1, 3, 5, 7, 9], [1, 1, 2, 3, 5], [2, 4, 6, 8, 10]);
var someFlattenedArray:Array = String(someNestedArray).split(",");
trace(someFlattenedArray.length);
|
|
As the length is 15, there are 15 elements rather than three elements with five elements each.
How can I concatenate two arrays together?
editConcatenating two arrays is a fairly simple operation. It requires the array1.concat(array2, array3...) method. This method does not flatten out nested arrays. The following code combines two arrays:
Code | Result |
---|---|
var array1:Array = new Array("a", "b", "c");
var array2:Array = new Array("d", 5, "f");
var array3:Array = array1.concat(array2);
trace(array3);
|
|
concat() should not be confused with join(), which will be covered later.
How can I add to and remove from an array?
editThere are several methods to add and remove elements from an array:
- array.pop()
- array.push(object1, object2...)
- array.shift()
- array.unshift(object1, object2...)
- array.splice(index of the first element, [number of elements,] [object1, object2...])
This is starting to get a bit intimidating, so let's go through each of them one by one.
Popping and pushing
editpop() removes the last element from the array and then returns the popped element. This example will show how the “pop” method works:
Code | Result |
---|---|
var myArray = new Array(1, 2, 3, 4);
var popped:Number = myArray.pop();
trace(popped);
trace(myArray);
|
|
Firstly, we declare the 'myArray' array with four elements: 1, 2, 3 and 4. Next, we declare the 'popped' variable. We then pop 'myArray' and assign the last element to the 'popped' variable. We then trace popped to see the element which was popped, then trace the new array.
push() adds one or more elements to the end of the array, and then returns the length of the new array:
Code | Result |
---|---|
var myArray = new Array(1, 2);
var newLength:Number = myArray.push(3, 4);
trace(newLength);
trace(myArray);
|
|
We first declare the 'myArray' array with two elements, 1 and 2. The second line pushes the values 3 and 4 into myArray (returning the new length), declares the 'newLength' variable, then assigns the new length to newLength.
Shifting and unshifting
editShifting and unshifting are similar to popping and pushing, but elements are added and removed from the beginning, not the end, of an array.
Here's an example of shifting:
Code | Result |
---|---|
var myArray = new Array(1, 2, 3, 4);
var shifted:Number = myArray.shift();
trace(shifted);
trace(myArray);
|
|
Firstly, we declare the 'myArray' array with four elements: 1, 2, 3 and 4. Next, we declare the 'shifted' variable. We then shift 'myArray' and assign the first element to the 'shifted' variable. We then trace shifted to see the element which was shifted, then trace the new array.
Here's an example of unshifting:
Code | Result |
---|---|
var myArray = new Array(3, 4);
var newLength:Number = myArray.unshift(1, 2);
trace(newLength);
trace(myArray);
|
|
We first declare the 'myArray' array with two elements, 3 and 4. The second line unshifts the values 1 and 2 into myArray (returning the new length), declares the 'newLength' variable, then assigns the new length to newLength.
Splicing
editSplicing an array is a more flexible and sophisticated process then pushing, popping, shifting and unshifting. (Slice, split, splice, shift... confused yet?) Splicing is the process of both removing and adding elements to an array. The splice() methods adds elements to and remove elements from the array, then returns the removed elements.
Let's look at the parameters again:
array.splice(index of the first element, [number of elements], [new element 1, new element 2...])
As you can see, only the first parameter is required. The first parameter indicates where you want to start doing your removing and adding work. It can be a normal index (0, 1, 2, 3...), or a negative one (-1 as the last element, -2, -3, -4...). If this is the only parameter you include, all the elements starting from that one will be removed:
Code | Result |
---|---|
var myArray:Array = [1, 2, 3, 4];
myArray.splice(2);
trace(myArray);
|
|
The second parameter is the number of elements to be removed. Let's alter the above example to remove only the 3:
Code | Result |
---|---|
var myArray:Array = [1, 2, 3, 4];
myArray.splice(2, 1);
trace(myArray);
|
|
The rest of the parameters are elements to be added to the array to replace the removed elements.
Code | Result |
---|---|
var myArray:Array = [1, 2, 3, 4];
myArray.splice(2, 1, 6, 7, 8);
trace(myArray);
|
|
We can also set the second parameter to 0 so that we add elements without removing any:
Code | Result |
---|---|
var myArray:Array = [1, 2, 3, 4];
myArray.splice(2, 0, 6, 7, 8);
trace(myArray);
|
|
How can I extract elements from an array?
editslice() returns certain elements in an array. Here are the parameters of slice():
array.slice([index of the first element], [index of the last element]);
Both parameters are optional. If the both elements are left blank, the whole array is copied:
Code | Result |
---|---|
var myArray:Array = [1, 2, 3, 4];
var secondArray:Array = myArray.slice();
secondArray.pop();
trace(secondArray);
trace(myArray);
var thirdArray:Array = myArray;
thirdArray.pop();
trace(thirdArray);
trace(myArray);
|
|
Again, the whole array is copied, not linked. In the above example, changing secondArray does not change the original myArray as myArray was copied to secondArray. However, changing thirdArray does change the original myArray as thirdArray only contains a link to myArray, not a copy of myArray.
Let's try again, this time with the first parameter:
Code | Result |
---|---|
var myArray:Array = [1, 2, 3, 4, 5];
var slicedArray:Array = myArray.slice(2);
trace(slicedArray);
|
|
Only everything from the element 2 is copied to slicedArray. Now let's try that a third time, with both parameters:
Code | Result |
---|---|
var myArray:Array = [1, 2, 3, 4, 5];
var slicedArray:Array = myArray.slice(2, 3);
trace(slicedArray);
|
|
Only the elements from element 2 to element 3 are copied to slicedArray.
What are joining and splitting?
editSometimes, we want to split a string into many substrings separated by a delimiter (a symbol showing where we should split the string), then tuck each substring into an array. In this case, we need the split method:
Code | Result |
---|---|
trace("Foo + Bar + Baz + Qux".split(" + "));
trace("Foo + Bar + Baz + Qux".split(" + ", 3));
trace("Foobar".split(""));
|
|
In the first trace, we used " + " as a delimiter to create an array containing the elements Foo, Bar, Baz and Qux. In the second trace, we limited the number of substrings to 3. In the third, the delimiter was a blank string, so the each substring consisted of one character.
Joining an array is the reverse operation of splitting a string. It creates a new string using array elements and a certain delimiter (the first and only parameter):
Code | Result |
---|---|
trace(["Foo", "Bar", "Baz", "Qux"].join(" + "));
trace(["F", "o", "o", "b", "a", "r"].join(""));
trace(["Foo", "Bar", "Baz", "Qux"].join());
|
|
In the first trace, we joined the Foo, Bar, Baz and Qux into a string separated by ' + '. In the second, we got the word 'Foobar' as we used an empty string as our delimiter. In the third, we produced the same effect as trace(String(["Foo", "Bar", "Baz", "Qux"].join()));
since we did not specify any delimiter and the default comma was used.
How can I sort arrays?
editSorting is a very complicated topic in ActionScript. In this section, we will try to do it!
How can I sort with sort()?
editThe sort() function can sort with one criterion.
How can I sort strings with Unicode code points?
editThe easiest way to sort a bunch of strings is to use Unicode code points. (We discussed Unicode code points way back in the chapter about operators.) This does not require any parameters:
Code | Result |
---|---|
var myArray:Array = ["spot", "lucky", "Rover", "Max"];
myArray.sort();
trace(myArray);
myArray = [1, 300, 2, 4, 6];
myArray.sort();
trace(myArray);
|
|
Note that Lucky and Max come before rover and spot because uppercase letters precede lowercase letters in Unicode. Also note that the numbers are also arranged according to their Unicode code points, not their magnitudes or values.
If we want the sort to ignore casing, we can pass an Array class constant, Array.CASEINSENSITIVE, into the sort() function:
Code | Result |
---|---|
var myArray:Array = ["spot", "lucky", "Rover", "Max"];
myArray.sort(Array.CASEINSENSITIVE);
trace(myArray);
|
|
Array.CASEINSENSITIVE can be replaced by the number 1.
How can I sort numbers?
editAs we've seen above, sort() sorts elements as strings by default. To sort numbers, we need to pass another Array class constant, Array.NUMERIC, into the sort() function:
Code | Result |
---|---|
var myArray:Array = [1, 300, -Infinity, 2, 4, 4.3e-3, Infinity, -3, 6, 0x2A];
myArray.sort(Array.NUMERIC);
trace(myArray);
|
|
Notice that negative infinity is always the smallest and infintiy is always the largest. Array.NUMERIC can be replaced by the number 16.
How can I sort with my own criterion?
editSometimes, using Unicode code points just isn't enough. In this case, we have to make our own functions. The first parameter of the sort() function is a function with two parameters which decide which of two values should come first. The function should return 1 if the first argument comes before the second argument, -1 if the second argument comes before the first, and 0 if it doesn't matter. If that sounds complicated, look at this example:
Code | Result |
---|---|
var myArray:Array = ["a good dog called spot", "a canine called lucky",
"a cute mammal called Rover", "an adorable animal called Max"];
function whichComesFirst(a:String, b:String):Number{
var dog1:String = a.substring(a.lastIndexOf(" ")+1).toUpperCase();
var dog2:String = b.substring(b.lastIndexOf(" ")+1).toUpperCase();
if(dog1 > dog2){
return 1;
} else if(dog1 < dog2) {
return -1;
} else {
return 0;
}
}
myArray.sort(whichComesFirst);
trace(myArray);
|
|
In the whichComesFirst function, we first extracted the last word from the string. Then, we converted everything to uppercase before comparing. That way, the case is ignored. This function sorts the array in a truly alphabetical order, similar to what we've achieved with Array.CASEINSENSITIVE.
How can I sort in descending order?
editTo sort in descending order, we pass on the value Array.DESCENDING into the first parameter:
Code | Result |
---|---|
var myArray:Array = ["spot", "lucky", "Rover", "Max"];
myArray.sort(Array.DESCENDING);
trace(myArray);
|
|
This can also be applied to custom criteria (note that the comparison function is the first parameter and the array constant is the second parameter in this case):
Code | Result |
---|---|
var myArray:Array = ["a good dog called spot", "a canine called lucky",
"a cute mammal called Rover", "an adorable animal called Max"];
function whichComesFirst(a:String, b:String):Number{
var dog1:String = a.substring(a.lastIndexOf(" ")+1).toUpperCase();
var dog2:String = b.substring(b.lastIndexOf(" ")+1).toUpperCase();
if(dog1 > dog2){
return 1;
} else if(dog1 < dog2) {
return -1;
} else {
return 0;
}
}
myArray.sort(whichComesFirst, Array.DESCENDING);
trace(myArray);
|
|
If we've already got another array constant as a parameter, we should use the bitwise OR operator (|)[2] to separate the two array constants.
Code | Result |
---|---|
var myArray:Array = [1, 300, -Infinity, 2, 4, 4.3e-3, Infinity, -3, 6, 0x2A];
myArray.sort(Array.NUMERIC | Array.DESCENDING);
trace(myArray);
|
|
What if I don't want to modify the original array?
editThe array constant Array.RETURNINDEXEDARRAY will make sort() return an array containing the new index of each number. For example, if the original array is [3, -1, 4], sort() will return [1, 0, 2], where the 3 is the second number (index 1), -1 is the first number (index 0), and 4 is the third number (index 2) in the sorted array.
Code | Result |
---|---|
var myArray:Array = [1, -3, 5, 7, 3];
var myIndices:Array = myArray.sort(Array.NUMERIC | Array.RETURNINDEXEDARRAY);
trace(myIndices);
var mySortedArray:Array = new Array();
for(i = 0; i < myIndices.length; i++){
mySortedArray[i] = myArray[myIndices[i]];
}
trace(mySortedArray);
|
|
Note that the terms are slightly different in databases. In databases, myIndices is known as an index, while our array indices are known as index keys. In this book, to avoid confusion, we will avoid using these terms.
What if I don't want repeated items?
editIf you use the Array.UNIQUESORT constant, Flash will return 0 instead of modifying the array if two or more elements are found to be equivalent. We'll use this constant in the fourth section, when we learn about exception handling.
How can I sort arrays with sortOn()?
editSometimes, we want to sort hashes or objects inside arrays, and it would be cumbersome to use custom criteria with sort(). That's where sortOn() comes in.
sortOn treats arrays like tables in a database. In a database, a table is a collection of entities, or records, with the same record structure. Each entity has several fields, each of which stores a particular attribute of the record. Sometimes, we need to use a query to sort the fields in a particular way. Sorting keys are the fields which are used to sort. The primary sort key is first used to sort the data. When there are two or more data with the same attribute in a certain field, the secondary sort key is used to sort those data. If there are still equivalent values, the tertiary sort key is used, and so on.
Let's say we have a table containing data on several books. We want to arrange the book titles in descending order first. If there are two books with the same title, then we sort by the author's last name in ascending order, then the author's first name in ascending order, and finally the publication year in descending order. In SQL, the syntax for doing this is:
SELECT *
FROM Books
ORDER BY Title DESC, Author_last ASC, Author_first ASC, Pub_year DESC;
Even if you have no knowledge of SQL, you can probably understand some of the code. Unfortunately, it's more complicated when it comes to ActionScript. Let's try to rewrite this SQL into ActionScript:
Code | Result |
---|---|
var books:Array = new Array({title:"The Adventures of Teddy Bear", last:"Bloggs", first:"Joe", year:1996},
{title:"Journey to the West", last:"Wu", first:"Cheng'en", year:1542},
{title:"The Adventures of Teddy Bear", last:"Bloggs", first:"Fred", year:2012});
books.sortOn(["title", "last", "first", "year"],
[Array.CASEINSENSITIVE | Array.DESCENDING, Array.CASEINSENSITIVE,
Array.CASEINSENSITIVE, Array.NUMERIC | Array.DESCENDING]);
for(var i:String in books){
trace(books[i].title + " by " + books[i].first + " "
+ books[i].last + " published in " + books[i].year);
}
|
|
That looks complicated! Let's break it down, one by one.
- Firstly, we created a new Array with three object literals. Each object has a title, a last name, a first name and a year. Note that each object here is an associative array.
- Next, we used sortOn. The first parameter of sortOn is an array containing the property names to be used as sort keys. The 0th element, title, is the primary sorting key, the 1th element, last, is the secondary sorting key, and so on.
- The second parameter is an array containing the array constants to be used for each sort. In this case, we want Array.CASEINSENSITIVE for the string fields, Array.NUMERIC for the publication year, and Array.DESCENDING the author and publication year. The bitwise OR operator is also used.
- Finally, we traced the new array from the 0th element to the 2nd.
It's not so difficult once we break it down, is it? We can also use it to sort instances of MovieClips and other classes. This seemingly unuseful technique comes in handy when you have a lot of elements to be presented. For example, if you're making a game with a level editor, you want a way to display the levels. The player can sort the levels by the date of publication, rating, difficulty, etc.
How can I reverse an array?
editreverse() is a quick and easy way to reverse arrays.
Code | Result |
---|---|
var myArray:Array = [1, 300, -Infinity, 2, 4, 4.3e-3, Infinity, -3, 6, 0x2A];
myArray.sort(Array.NUMERIC | Array.DESCENDING);
trace(myArray);
myArray.reverse();
trace(myArray);
|
|
Conclusion
editWe've gone through two chapters in the second section, and so far, we've only been manipulating data without any real output on the screen. That might not be too satisfying for you, so let's move on to the very heart and soul of the Flash application: the MovieClip.
Notes
edit- ↑ Again, because of the existence of a global function Array(), you don't have to put the 'new' before Array() if you don't want to.
- ↑ The bitwise OR operator is outside the scope of this book, so we will not discuss how exactly it works.
MovieClips
Key concepts:
ActionScript 2.0 revolves around movie clips. (They have decreased in importance in AS3, but they remain an important part of Flash applications.) In this long chapter, we will go through the nitty-gritty details of movie clips.
What are some basic movie clips concepts to know?
editWhat is the stage?
editThe stage is the area where all the action happens. The Stage class is a class containing static functions, static properties and event handlers related to the stage.
How can I get the stage dimensions?
editThe first properties we need to know are Stage.width and Stage.height. These are read-only properties, which means we can retrieve their values, but cannot change them during runtime. They are set in the Flash IDE itself through the Modify > Document window. The following code retrieves the coordinates of the centre point of the stage:
Code | Result |
---|---|
var centrePoint:Object = {x:Stage.width/2, y:Stage.height/2};
trace(centrePoint.x);
trace(centrePoint.y);
|
|
Note how we created an object with the properties x and y. This will come in handy later in this chapter and in the second section.
How can I set the application to full-screen mode?
editSometimes, we want the stage to, well 'jump out of the box' of the player or browser and occupy the whole screen. This is called full-screen mode. The Stage class has functions for doing so. Note that full-screen mode must be initiated by user input, and the application is not allowed to do it itself. It is also worth noting that keyboard input is disabled in full-screen mode. Furthermore, full-screen mode can only be used when the application is embedded in a webpage. This is because of security reasons. The HTML code also needs to be slightly altered to support the full-screen mode.
The Stage.displayState should be altered in order to toggle in and out of full-screen mode.
What exactly is a timeline?
editBy now, you should be quite familiar with Flash timelines, but how exactly do they work?
When a Flash application without ActionScript runs, a playhead runs through the frames of the main timeline and plays them one by one. When there are MovieClip symbols on the stage, they each have a playhead and a timeline, too. The speed at which the playhead moves is called the frame rate, which is measured in frames per second (fps). For example, an application with 10 fps moves ten times a second.
Now, this is a bit different when ActionScript comes in. The first thing to remember is that the code in each frame is executed before the frame is displayed. For instance, if you put gotoAndStop(3);
in the first frame of a movie clip, it will jump directly to the third frame without displaying the first frame. There are several functions which move the playhead, and we've learnt them in the first section, so here's a quick refresher:
play()
andstop()
will play and stop playing the frames in order respectively.gotoAndPlay(frame)
andgotoAndStop(frame)
will go to the specified frame, then play and stop the Flash respectively.prevFrame()
andnextFrame()
go to the previous and next frame respectively. Unless there is astop()
statement on the target frame, they will play.
You might think that once the playhead is stopped, e.g. with gotoAndStop
or stop
, the frame rate is no longer significant. That cannot be further from the truth. Remember events? When events are triggered, the screen does not change immediately. Instead, it waits till the next time the frame is 'entered', which happens at the frame rate. There are two exceptions to this rule, both involving a special function; we'll discuss one later in this chapter, and another in the next chapter.
The onEnterFrame
event of the MovieClip class allows code to be executed constantly, at the frame rate. The following example shows how to make a box fall:
Code | Result |
---|---|
//Assume that 'box' is a MovieClip instance on the stage.
onEnterFrame = function(){
box._y++;
trace("The box moved!");
}
|
|
Now suppose we want the bottom edge of the application to act as the ground. How should be change the code?
Code | Result |
---|---|
//Assume that 'box' is a MovieClip instance on the stage.
onEnterFrame = function(){
if(box._y != Stage.height - box._height){
box._y++;
trace("The box moved!");
if(box._y > Stage.height - box._height){
box._y = Stage.height - box._height;
}
}
}
|
|
What are scenes?
editThe Main Timeline has a limited number of frames. If you wanted to create a Flash application involving a lot of frames, such as a detective game, it may not be sufficient. In addition, in an application with lots of frames, it may be irritating if you keep all the frames in the same timeline. Fortunately, there is one solution to this problem: scenes. A Flash application may have lots of scenes. Click on the Window menu in the Flash IDE to create, delete and rename scenes. There are four functions that allow you to change scenes:
- prevScene(scene);
- nextScene(scene);
- gotoAndPlay(scene, frame);
- gotoAndStop(scene, frame);
You might be wondering why gotoAndPlay popped up again! Well, this gotoAndPlay is not the same as the MovieClip method gotoAndPlay(). Firstly, MovieClip.gotoAndPlay(frame) and MovieClip.gotoAndStop(frame) don't require the first scene parameter. All four functions are global functions, and it doesn't matter where you call them; they always, without exception, move the main timeline. Here's an example with three scenes (firstScene, secondScene, lastScene):
Code | Result |
---|---|
On the first frame of the first scene: stop();
trace("Welcome to firstScene!");
Mouse.addListener(this);
this.onMouseDown = function(){
if(Scene.currentScene != "lastScene"){
nextScene();
} else {
gotoAndPlay("firstScene", 1);
}
}
On the first frame of the second scene: trace("Welcome to secondScene!")
On the first frame of the third scene: trace("Welcome to lastScene!")
|
|
Unfortunately, Scene.currentScene is not available for older Macromedia versions of Flash. Therefore, you may need to devise some clever technique to work around this problem. For example, you could put a movie clip with a weird name off the stage of the last scene. If that movie clip is defined, then the mouse click should result in a move to the first scene.
Can I name frames?
editFrame numbers are usually quite difficult to remember. It is often a good idea to name your most important frames. Frame names are called frame labels. To label a frame, type in the name in the properties panel. The label can then replace the frame number in the gotoAndPlay function (both MovieClip and global).
Code | Result |
---|---|
//Assume that the fps is 20 and someImportantFrame is frame 5.
var timePassed:Number = 0;
onEnterFrame = function(){
if(_currentframe == 1){
timePassed++;
if(timePassed >= 20){
gotoAndPlay("someImportantFrame");
}
} else if(_currentframe == 5){
trace("Welcome to Frame 5!");
}
}
|
|
How can I change the appearance and position of a MovieClip?
editMovie clips and coordinates
editAs we've already discussed, _x and _y are the x- and y-coordinates of (the top-left corner of) a movie clip in its parent. That's all good, but how can we find the coordinates of a movie clip on the stage when it is two levels above the main timeline? How about the opposite? Can we find the coordinates of a movie clip on the stage in terms of another movie clip on the stage?
Local coordinates are the coordinates of a point inside another movie clip, while global coordiantes (also known as stage coordinates) are the coordinates of a point on the stage. The MovieClip.localToGlobal() and MovieClip.globalToLocal() funtions convert between local and local coordinates. Let's try them one by one.Put an apple movie clip instance on the stage, then place a worm movie clip instance inside it. Our job is to find the coordinates of the worm, relative to the stage. Put the following code on the first frame of the main timeline:
Code | Result |
---|---|
var someCoordinates:Object = {x:apple.worm._x, y:apple.worm._y};
apple.worm.localToGlobal(someCoordinates);
trace("Global coordinates: (" + someCoordinates.x + ", " + someCoordintes.y));
|
|
_xscale and _yscale
edit_xscale is the ratio of a movie clip's original width in the library and its current width after scaling. _yscale is the ratio of a movie clip's original height in the library and its current height after scaling. They are not related to the _x and _y properties! If _xscale and _yscale are equal, then the aspect ratio of the movie clip is unchanged.
Code | Result |
---|---|
apple._width = 10;
apple._height = 10;
if(apple._xscale == apple._yscale){
trace("Same aspect ratio!");
} else {
trace("Different aspect ratio!");
}
trace("Global coordinates: (" + someCoordinates.x + ", " + someCoordintes.y));
|
|
Opacity
edit_alpha is a measure (from 0 to 100) of a movie clip's opacity. If a movie clip has an _alpha value of 0, it is completely transparent; if its _alpha is 100, it is completely opaque. Try playing around with _alpha!
Code | Result |
---|---|
apple._alpha = 0;
|
|
What is focus?
editHave you ever had two windows on your screen at the same time? When you, say, type, the text would affect only one of the windows. The affected window has focus and the other window does not.
Movie clips also have focus.
How do movie clips respond to mouse actions?
editWhat are the events associated with the mouse?
editHow can the user drag movie clips?
editHow can I use detect collisions?
editHow can I create movie clips dynamically?
editWhat is depth?
editHow can I use movie clips from the library?
editHow can I create empty movie clips?
editHow can I duplicate movie clips?
editHow can I destroy movie clips?
editHow can I change a movie clip's depth?
editWhat is the drawing API?
editIs there anything else to learnt about movie clips?
edit- _quality
- getSWFVersion
Conclusion
editNotes
edit
Math Class
Key concepts:
Maths are very important in Flash applications. Let's learn how to use mathematical functions in ActionScript!
Handling numbers
editThere are several functions of the Math class that can manipulate numbers for us:
- Math.abs(Number): Finds the absolute value of a number
- Math.ceil(Number): Rounds a number up to the nearest integer
- Math.floor(Number): Rounds a number down to the nearest integer
- Math.round(Number): Rounds a number off to the nearest integer
- Math.max(Number 1, Number 2): Returns the larger of two numbers
- Math.min(Number 1, Number 2): Returns the smaller of two numbers
- Math.random(): Returns a random number smaller than 1 and larger than or equal to 0
Let's look at a quick example:
Code | Result |
---|---|
var myNumber:Number = -12.3;
trace(Math.abs(myNumber));
trace(Math.ceil(myNumber));
trace(Math.floor(myNumber));
trace(Math.round(myNumber));
trace(Math.max(Math.ceil(myNumber), Math.floor(myNumber)));
trace(Math.min(Math.ceil(myNumber), Math.floor(myNumber)));
trace(Math.floor(Math.random() * 12)+1);
|
|
Note the technique used in the last line to produce random numbers. Math.random() is multiplied by 12, rounded down (giving a random integer from 0 to 11) and then one is added (giving a random integer from 1 to 12).
Exponents, roots and logarithms
editTrigonometry and pi
edit