This is theprint version ofIntroduction to ActionScript 2.0 You won't see this message or any elements not part of the book's content when you print orpreview 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 to ActionScript 2.0 | ||
| Printable version | Variables and Data Type | |
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:
If you do not, check out the official documentation for your version of Flash first.
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!
Firstly, 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.
| Introduction to ActionScript 2.0 | ||
| Introduction | Printable version | Operators |
Key concepts:
Before we start doing any programming work, we need to work on our basics. Let's start with data types and variables.
When we work on a Flash project, there are a lot of 'entities' we need to manage: numbers, text, pictures, and so on. Adata type is a type of data in our application.
Aprimitive 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 ofliterals, which means they never change and aren't contained in a variable. For example, you can't change the value of 3254, can you?
DataType(Value) is used to convert between primitive data types:[1]
You can't convert from string to Boolean.
Sometimes, primitive data types just aren't enough. we need to useclasses.
Any data type that is not of a primitive data type is acomposite data type. Composite data types are calledclasses.[2] TheObject 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 aninstance of the class. The name of an instance is, surprisingly enough, called aninstance name.
Every 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.)
Now that you've got this far, you deserve to start your first ActionScript project!
Open 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 |
|---|---|
varHello: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:
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 isidentifier, 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 calledstrong typing your variable.)[3]As you have probably noticed, the syntax fordeclaring a variable (i.e. telling the computer to set aside some of its precious RAM to store your variable) is as follows:
varvariableName:DataType;
Now let's take a look at the second line. The equal sign is called theassignment operator It is used toassign 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.
There's a quicker way to declare a variableand assign a value to it.
| Code | Result |
|---|---|
varHello:String="Hello world!";trace(Hello); |
|
This is calledinitialising a variable.
The syntax for initialising a variable is as follows:
varVariableName:DataType =Value;
Like most programming languages, ActionScript does not allow certain 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 tonaming 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.
To delete a variable, we need to use the word 'delete':
| Code | Result |
|---|---|
varsomeString:String="Hello";deletesomeString;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.
Now that you have an idea how variables work, let's move on to the second chapter: Operators.
varHello;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.
| Introduction to ActionScript 2.0 | ||
| Variables and Data Type | Printable version | Functions |
Key concepts:
Anoperator is something, usually a sign like + or -, that is used to manipulate different entities. The entities manipulated are calledoperands. 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.)
An arithmetic operator is an operator that does maths for you. The four basic arithmetic operators are as follows:
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 anexpression 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.
One peculiarity of Flash is that + acts as both the addition operator and thetext 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 are operators which compare two entities and return a Boolean value.
The equality operator (==) compares two entites and determines whether they are exactly the same. If it's the same, it returnstrue; otherwise, it returnsfalse. 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 returntrue if they are referring to the same entity. Even if we have two distinct identical entities, the equality operator will returnfalse. 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 returntrue 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"); |
|
Flash provides several inequality operators for all your comparing needs.
The first operator is !=. != does the opposite of ==: if the two are equal, it returnsfalse, 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:
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 Unicodecode points in order to be compared. SeeUnicode/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.
Like most languages, the most importantlogical operators are AND, OR and NOT.
&& is ActionScript's AND operator. Its operands must be Boolean. If both operands aretrue, it returnstrue; otherwise, it returnsfalse.
| 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 istrue, it returnsfalse; otherwise, it returnstrue.
| 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 becomestrue andtrue becomesfalse.
| Code | Result |
|---|---|
trace(!false);trace(!true);trace(!true&&true);trace(!false&&true); |
|
We'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:
What does this mean?
| Code | Result |
|---|---|
varstring_1:String="Wikibooks";varstring_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.varnicestDog: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.
There 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:
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 |
|---|---|
varnumber_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.
So 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 statementsper 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, whilea /= 2 returns half the original value of a.
The following code may look counter-intuitive, but it works:
| Code | Result |
|---|---|
vara=6;varsome_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.
ActionScript offers four incremental/decremental operators:
variableName++++variableNamevariableName----variableNameBoth 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 |
|---|---|
varmyFirstNumber: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 statementsper 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 |
|---|---|
varmyFirstNumber:Number=10;trace(myFirstNumber++);trace(myFirstNumber); |
|
| Code | Result |
|---|---|
varmyFirstNumber:Number=10;trace(++myFirstNumber);trace(myFirstNumber); |
|
In our first example,myFirstNumber was tracedbefore 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 tracedafter the increment operation, so we can already see the 11 in the first trace.
Remember 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 andoperator associativity.
When one operator is always evaluated before the other, we call it operator precedence.
Here's a quick lowdown on operator precedence:
If we want a certain operation to have higher precedence, we should use thegrouping 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 |
|---|---|
vara=6;varsomeNumber: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 |
|---|---|
vara=6;varsomeNumber:Number=3+a+=1;trace(someNumber);trace(a); |
|
This is becausevar 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.
Consider the expressionsomeNumber = 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 |
|---|---|
varsomeNumber: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 valuetrue. Now to the right side. In4 - 3 >= 1, 4 - 3 = 1, so 1 >= 1 returnstrue. Since both sides of the && are true, the trace statement returnstrue.
Now that we've learnt all the difficult operators, let's end the chapter with a very simple concept.
Acomment 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. */vara=6;varsomeNumber: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, calledcommenting out, is also achieved with comments.
Now that we've learnt all our operators, we can move on to the next chapter: functions.
| Introduction to ActionScript 2.0 | ||
| Operators | Printable version | Properties and Methods |
Key concepts:
Now that we've learnt all our operators, we can get to the next part: functions.
In 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, afunction 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.)
Here's a simple function with no outputs and no inputs. Look at the code and we'll explain it step by step:
| Code | Result |
|---|---|
varsomeNumber:Number=5;functionaddOneToSomeNumber():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.: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.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 thebody 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.
In order to use a function, we need tocall it. Let's look at the above example again:
| Code | Result |
|---|---|
varsomeNumber:Number=5;functionaddOneToSomeNumber():Void{someNumber++;}addOneToSomeNumber();trace(someNumber); |
|
In the function call above, we just called the functionaddOneToSomeNumber. 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.
In programming, the input of a function is called aparameter orargument.[1] Let's modify our addOneToSomeNumber function to accommodate the addition of any number to someNumber:
| Code | Result |
|---|---|
varsomeNumber:Number=5;functionaddAnyNumberToSomeNumber(anyNumber:Number):Void{someNumber+=anyNumber;}addAnyNumberToSomeNumber(2);trace(someNumber);trace(anyNumber); |
|
In this example, the codeanyNumber:Number is put into the brackets. This is the input of the function and is written asvariableName:DataType.[2] Once input, anyNumber is known as alocal 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 keywordundefined. Whenever we try to refer to a value that is not defined, Flash will return the valueundefined. We will discussundefined and its twin brothernull 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 |
|---|---|
varsomeNumber:Number=5;functionaddTwoNumbersToSomeNumber(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.
Look 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 |
|---|---|
varsomeNumber:Number=5;functionaddTwoNumbers(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 |
|---|---|
varsomeNumber:Number=5;functionaddTwoNumbers(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 |
|---|---|
varsomeNumber:Number=5;functionaddTwoNumbers(originalNumber:Number,anyNumber:Number):Number{return(originalNumber+anyNumber);}varyetAnotherNumber: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:
functionfunctionName(parameter1:DataType1,parameter2:DataType2...):ReturnDataType{Statements; returnvalue;}Like 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().
When a function is called, it is called acallee. When a function is called by another function, the calling function is called thecaller.
Thearguments object of a function can find the caller and the callee. The following example traces the caller and callee:
| Code | Result |
|---|---|
functionuselessFunction():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.
If 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 |
|---|---|
varsomeFunction:Function=function(someString:String):Void{trace(someString);}someFunction("Hello world!"); |
|
By now, you may be wondering where you got thetrace function when you've never defined it anywhere. Read the next chapter to find out!
| Introduction to ActionScript 2.0 | ||
| Functions | Printable version | Control Statements |
Key concepts:
this,this._parentwithnull,undefinedProperties and methods are the two components that constitute a class. Aproperty is a variable that belongs to a certain class. Amethod is a function that belongs to a certain class. This chapter is about this important twosome.
ActionScript provides a huge number ofbuilt-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 belovedtrace() is one of these functions. These functions are calledtop-level functions orglobal 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]
We 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:Themain 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 adynamic class. We will talk about dynamic classes in the third section.
The 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 invar 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.
this and_parent?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 withthis.
| 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 usethis is when a parameter and a timeline variable have the same name. In this case, one must putthis before the timeline variable so that the computer knows you're not talking about the local variable. Here's an example:
| Code | Result |
|---|---|
varsomeString:String="random text";functionstringTogether(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: varcrunchiness: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: varcrunchiness: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!
with?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: varcrunchiness:Number=7;varsweetness:Number=4; In the first frame of the apple symbol: varjuiciness: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 usewith to solve this problem:
| Code | Result |
|---|---|
In the first frame of the main timeline: varcrunchiness:Number=7;varsweetness:Number=4; In the first frame of the apple symbol: varjuiciness: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.
Sometimes, 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 |
|---|---|
varcurrentAnimal:String="cat";vardogFood:String="biscuits";varcatFood:String="fish";varfishFood: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]
In 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: varsomeFruit:MovieClip=apple;trace(apple.juiciness);trace(apple["juiciness"]); In the first frame of the apple symbol: varjuiciness:Number=6; |
|
The following are some MovieClip properties that will be used throughout the rest of the section.[4]
_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.
Calling 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.
Aconstructor 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]
varvariableName:DataType = newDataType(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.varspot:Dog=newDog("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(newNumber()); |
|
Firstly, 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]
varvariableName:Object = {property1:value1,property2:value2, ...,method1:function1,method2:function2 ...};Thefunction1,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 |
|---|---|
varsomeObject: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.
null andundefined?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 andundefined 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 returnstrue), but not the strict equality operator (i.e.null === undefined returnsfalse). Consider the following example:
| Code | Result |
|---|---|
varsomeNumber:Number;trace(someNumber);someNumber=null;trace(someNumber);varsomeString:String=undefined;trace(undefined==null);trace(undefined===null); |
|
In this example, someNumber is at firstundefined, then set tonull. Next, someString is set toundefined. (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 withnull andundefined.
| Code | Result |
|---|---|
varsomeBoolean:Boolean;trace(!someBoolean);varsomeNumber: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.
| Introduction to ActionScript 2.0 | ||
| Properties and Methods | Printable version | Event Handling |
Key concepts:
default,break;while anddo ... while loopsfor ... in loopsarguments with conditions and loopsSometimes, 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 aboutcontrol statements, which control how statements are executed.
Aselection statement, also known as aconditional 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 thecondition.
if?Consider the following example:
| Code | Result |
|---|---|
varisHappy:Boolean=true;if(isHappy){trace("I am happy!");} |
|
In the above code, the words 'I am happy!' is traced ifisHappy is true. What if we wanted to trace 'I am unhappy.' ifisHappy is not true?
| Code | Result |
|---|---|
functiontraceMood():Void{if(isHappy){trace("I am happy!");}else{trace("I am unhappy.");}}varisHappy:Boolean=true;traceMood();isHappy=falsetraceMood(); |
|
In the above code, we usedelse to trace the words 'I am unhappy.' ifisHappy 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 |
|---|---|
functiontraceMood():Void{if(isHappy){trace("I am happy!");}elseif(isHappy==false){trace("I am unhappy.");}else{trace("Meh.");}}varisHappy: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 |
|---|---|
functionsomeCallee(){if(arguments.caller==someCaller){someNumber++;trace("No, *I* get to say that Hello World line!");arguments.caller();}}functionsomeCaller(){trace("Hello world!");if(someNumber==5){someCallee();}}varsomeNumber: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.
switch statements?Sometimes, we have several conditions and it would be infeasible to make anif statement for every single one of them. In this case, we may use aswitch statement. The syntax is as follows:
switch(variable){ casevalue: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 |
|---|---|
vartoday:Number=5;switch(today){case1:trace("Monday");break;case2:trace("Tuesday");break;case3:trace("Wednesday");break;case4:trace("Thursday");break;case5:trace("Friday");break;case6:trace("Saturday");break;case7: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 thebreak; statement tells the computer to break out of the switch statement. If thebreak; statements are not included, the computer will continue executing the statements of the cases below it. For example:
| Code | Result |
|---|---|
vartoday:Number=5;switch(today){case1:trace("Monday");case2:trace("Tuesday");case3:trace("Wednesday");case4:trace("Thursday");case5:trace("Friday");case6:trace("Saturday");case7:trace("Sunday");} |
|
Sometimes, we need to perform an action many times. This is where loops come in handy.
for loop?Afor loop has a variable called aloop 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(vari:Number=0;i<10;i+=2){trace("Wikibooks is awesome.");} |
|
The following steps were involved:
Like with switch statements, it is possible to break the loop with abreak; statement:
| Code | Result |
|---|---|
varsomeVariable:Number=3;for(vari: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 |
|---|---|
varsomeVariable:Number=3;for(vari: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 createinfinite loops. Infinite loops crash applications (warning: donot try this at home):
| Code | Result |
|---|---|
varsomeVariable:Number=3;for(vari:Number=0;i>-1;i++){trace("Wikibooks is awesome.");someVariable++;if(someVariable>5){break;}} |
|
Anarray is an object that 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 calledarray 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 |
|---|---|
varmonths:Array=newArray();months[0]="January";months[1]="February";months[2]="March";...months[11]="December";trace(months[0]); |
|
The position of an array element is called itsindex. Indices start with 0, not 1. We can access an array element using the syntaxarrayName[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 isnot 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 |
|---|---|
vardogs:Array=newArray();dogs[0]="Spot";dogs[1]="Lucky";dogs[2]="Max";...dogs[9]="Rover";for(vari: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.
In 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 |
|---|---|
functiongrabStrings(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 |
|---|---|
functiontraceStrings(string1:String,string2:String,string3:String,string4:String):Void{for(vari: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.
while anddo ... while loops??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 |
|---|---|
varmonths:Array=newArray();months[0]="January";months[1]="February";months[2]="March";...months[10]="December";vari: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 returnstrue 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 |
|---|---|
vardays:Array=newArray();days[0]="Monday";days[1]="Tuesday";days[2]="Wednesday";days[10]="Sunday";vari: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.
for ... in loop?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 itsvisibility, which we'll cover in the third section. The syntax is as follows:
for(Declaration of the counter without initialisation inTarget 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 |
|---|---|
vardogs:Array=newArray();dogs[0]="Spot";dogs[1]="Lucky";dogs[2]="Max";...dogs[9]="Rover";for(vari:Stringindogs){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 anObject instance.
| Code | Result |
|---|---|
varspot:Object={species:"chihuahua",colour:"brown"}for(vari:Stringinspot){trace(spot[i]);} |
|
In this case, Flash looped through both visible properties of spot (species and colour) and returned their values.
So 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.
| Introduction to ActionScript 2.0 | ||
| Control Statements | Printable version | Primitive Data Types |
Key concepts:
Anevent 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.
Anevent 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.
The 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:
Since 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 calledcallback notification.
Polling 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.
Since 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.
| Introduction to ActionScript 2.0 | ||
| Event Handling | Printable version | Arrays |
Key concepts:
After cramming all those basic concepts in your head, you deserve a break! This chapter is all about primitive data types.
Awrapper 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:
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(newNumber());trace(newString());trace(newBoolean()); |
|
Although traced as true, new Boolean() is neither true nor false.
You can also put the literal into the first parameter:
| Code | Result |
|---|---|
trace(newString("Hello world!"));trace(newNumber(123));trace(newBoolean(true)); |
|
There's a slight difference between a 'string' and a 'string object'. Look at the following example:
| Code | Result |
|---|---|
trace(123instanceofNumber);trace(newNumber(123)instanceofNumber);trace(typeof123);trace(typeofnewNumber(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(newNumber(123).valueOf()instanceofNumber); |
|
To convert the other way, simple call the constructor function.
The 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 itsindex. 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!
The following functions are related to characters in ActionScript:
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 astatic 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.
Asubstring is a string inside another string. There are three ways to find a substring when we know its position in a string:
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:
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")); |
|
newline 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!"); |
|
ActionScript 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.
Apart from the usual floating-point decimals and integers we manipulate, ActionScript has five special numbers, allstatic properties of Number:
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 areconstants. 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_INFINITYand 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.
Back 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(newArray(12,32,34)));trace(String(someMovieClip));trace(String(newSound));trace(String(someFunction));functionsomeFunction():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.
Now that we've learnt all about primitive data types, we will learn how to manipulate arrays.
| Introduction to ActionScript 2.0 | ||
| Primitive Data Types | Printable version | MovieClips |
Key concepts:
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.
In computer programming, there are actually two kinds of arrays,indexed arrays andassociative arrays (also known ashashes). 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 |
|---|---|
vardogs:Array=newArray(10);dogs[0]="Spot";dogs[1]="Lucky";dogs[2]="Max";...dogs[9]="Rover";trace(dogs[0]);varfruits:Array=newArray("Apples","Bananas","Oranges","Pears");trace(fruits[2]);varmonths: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].
Amultidimensional array, or anested array, is an array that contains arrays as elements. It can represent data in a tabular form. For instance:
| Code | Result |
|---|---|
varmultiplicationTables:Array=newArray(10);for(vari:Number=0;i<multiplicationTables.length;i++){multiplicationTables[i]=newArray(10);for(varj: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 |
|---|---|
varsomeNestedArray:Array=newArray([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 |
|---|---|
varsomeNestedArray:Array=newArray([1,3,5,7,9],[1,1,2,3,5],[2,4,6,8,10]);varsomeFlattenedArray:Array=String(someNestedArray).split(",");trace(someFlattenedArray.length); |
|
As the length is 15, there are 15 elements rather than three elements with five elements each.
Concatenating two arrays is a fairly simple operation. It requires thearray1.concat(array2,array3...) method. This method does not flatten out nested arrays. The following code combines two arrays:
| Code | Result |
|---|---|
vararray1:Array=newArray("a","b","c");vararray2:Array=newArray("d",5,"f");vararray3:Array=array1.concat(array2);trace(array3); |
|
concat() should not be confused with join(), which will be covered later.
There are several methods to add and remove elements from an array:
This is starting to get a bit intimidating, so let's go through each of them one by one.
pop() removes the last element from the array and then returns the popped element. This example will show how the “pop” method works:
| Code | Result |
|---|---|
varmyArray=newArray(1,2,3,4);varpopped: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 |
|---|---|
varmyArray=newArray(1,2);varnewLength: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 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 |
|---|---|
varmyArray=newArray(1,2,3,4);varshifted: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 |
|---|---|
varmyArray=newArray(3,4);varnewLength: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 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 |
|---|---|
varmyArray: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 |
|---|---|
varmyArray: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 |
|---|---|
varmyArray: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 |
|---|---|
varmyArray:Array=[1,2,3,4];myArray.splice(2,0,6,7,8);trace(myArray); |
|
slice() 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 |
|---|---|
varmyArray:Array=[1,2,3,4];varsecondArray:Array=myArray.slice();secondArray.pop();trace(secondArray);trace(myArray);varthirdArray:Array=myArray;thirdArray.pop();trace(thirdArray);trace(myArray); |
|
Again, the whole array iscopied, notlinked. 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 |
|---|---|
varmyArray:Array=[1,2,3,4,5];varslicedArray: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 |
|---|---|
varmyArray:Array=[1,2,3,4,5];varslicedArray:Array=myArray.slice(2,3);trace(slicedArray); |
|
Only the elements from element 2 to element 3 are copied to slicedArray.
Sometimes, we want to split a string into many substrings separated by adelimiter (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 astrace(String(["Foo", "Bar", "Baz", "Qux"].join())); since we did not specify any delimiter and the default comma was used.
Sorting is a very complicated topic in ActionScript. In this section, we will try to do it!
The sort() function can sort with one criterion.
The 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 |
|---|---|
varmyArray: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 |
|---|---|
varmyArray:Array=["spot","lucky","Rover","Max"];myArray.sort(Array.CASEINSENSITIVE);trace(myArray); |
|
Array.CASEINSENSITIVE can be replaced by the number 1.
As 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 |
|---|---|
varmyArray: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.
Sometimes, 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 |
|---|---|
varmyArray:Array=["a good dog called spot","a canine called lucky","a cute mammal called Rover","an adorable animal called Max"];functionwhichComesFirst(a:String,b:String):Number{vardog1:String=a.substring(a.lastIndexOf(" ")+1).toUpperCase();vardog2:String=b.substring(b.lastIndexOf(" ")+1).toUpperCase();if(dog1>dog2){return1;}elseif(dog1<dog2){return-1;}else{return0;}}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.
To sort in descending order, we pass on the value Array.DESCENDING into the first parameter:
| Code | Result |
|---|---|
varmyArray: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 |
|---|---|
varmyArray:Array=["a good dog called spot","a canine called lucky","a cute mammal called Rover","an adorable animal called Max"];functionwhichComesFirst(a:String,b:String):Number{vardog1:String=a.substring(a.lastIndexOf(" ")+1).toUpperCase();vardog2:String=b.substring(b.lastIndexOf(" ")+1).toUpperCase();if(dog1>dog2){return1;}elseif(dog1<dog2){return-1;}else{return0;}}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 |
|---|---|
varmyArray:Array=[1,300,-Infinity,2,4,4.3e-3,Infinity,-3,6,0x2A];myArray.sort(Array.NUMERIC|Array.DESCENDING);trace(myArray); |
|
The 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 |
|---|---|
varmyArray:Array=[1,-3,5,7,3];varmyIndices:Array=myArray.sort(Array.NUMERIC|Array.RETURNINDEXEDARRAY);trace(myIndices);varmySortedArray:Array=newArray();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 anindex, while our array indices are known asindex keys. In this book, to avoid confusion, we will avoid using these terms.
If 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.
Sometimes, 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, atable is a collection of entities, orrecords, with the same record structure. Each entity has severalfields, each of which stores a particular attribute of the record. Sometimes, we need to use aquery to sort the fields in a particular way.Sorting keys are the fields which are used to sort. Theprimary sort key is first used to sort the data. When there are two or more data with the same attribute in a certain field, thesecondary sort key is used to sort those data. If there are still equivalent values, thetertiary 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*FROMBooksORDERBYTitleDESC,Author_lastASC,Author_firstASC,Pub_yearDESC;
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 |
|---|---|
varbooks:Array=newArray({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(vari:Stringinbooks){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.
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.
reverse() is a quick and easy way to reverse arrays.
| Code | Result |
|---|---|
varmyArray: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); |
|
We'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.
| Introduction to ActionScript 2.0 | ||
| Arrays | Printable version | Date and Time |
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.
Thestage 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.
The first properties we need to know are Stage.width and Stage.height. These areread-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 |
|---|---|
varcentrePoint: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.
Sometimes, we want the stage to, well 'jump out of the box' of the player or browser and occupy the whole screen. This is calledfull-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.
By now, you should be quite familiar with Flash timelines, but how exactly do they work?
When a Flash application without ActionScript runs, aplayhead 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 theframe rate, which is measured inframes 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 putgotoAndStop(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. withgotoAndStop orstop, 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.
TheonEnterFrame 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;}}} |
|
The 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:
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) andMovieClip.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.
Frame numbers are usually quite difficult to remember. It is often a good idea to name your most important frames. Frame names are calledframe 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.vartimePassed:Number=0;onEnterFrame=function(){if(_currentframe==1){timePassed++;if(timePassed>=20){gotoAndPlay("someImportantFrame");}}elseif(_currentframe==5){trace("Welcome to Frame 5!");}} |
|
As 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, whileglobal coordiantes (also known asstage coordinates) are the coordinates of a point on the stage. TheMovieClip.localToGlobal() andMovieClip.globalToLocal() functions 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 |
|---|---|
varsomeCoordinates:Object={x:apple.worm._x,y:apple.worm._y};apple.worm.localToGlobal(someCoordinates);trace("Global coordinates: ("+someCoordinates.x+", "+someCoordintes.y)); |
|
_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 theaspect 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)); |
|
_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; |
Have 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 hasfocus and the other window does not.
Movie clips also have focus.
To detect collision between Movie Clips its actually quite simple,
there are two methods:
if(MovieClip1.hitTest(MovieClip2)) will detect if MovieClip1 and 2 hitboxes are touching.
and
if(MovieClip1.hitText(x,y,flag)) will detect if the MovieClip1 hitbox is touching the x and y position.
| Introduction to ActionScript 2.0 | ||
| Sounds | Printable version | Other Classes |
Key concepts:
Maths are very important in Flash applications. Let's learn how to use mathematical functions in ActionScript!
There are several functions of the Math class that can manipulate numbers for us:
Let's look at a quick example:
| Code | Result |
|---|---|
varmyNumber: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).