Using the Core Classes

     

Using the Core Classes

Macromedia classifies 11 of Flash's built-in classes, shown in Table 21.2, as core classes. Of these, arguments is covered in Chapter 20. The others are covered in this section.

The core classes provide basic data-manipulation capabilities useful for a wide variety of programming tasks .

Table 21.2. Core Objects

Object

Represents

arguments

Function arguments (in an array)

Array

Ordered list

Boolean

True/false or other duality

Date

Calendar date/time

Error

An error condition

Function

A function

Math

Math functions and constants

Number

Numbers

Object

Unordered collection

String

Alphanumeric data

System

The computer system on which the SWF is running


The Array Class

An array is an ordered, numbered collection of data items. You use an array like a filing cabinet for data. Each element (item in the array) is like a file drawer labeled with an index number. Indexes start at and count up through the positive integers. The whole array also needs to be contained in a data item so that you can refer to it as a single object.

Table 21.3 summarizes the three types of data required to work with an array: elements, indexes, and a data container for the whole array.

Table 21.3. Three Types of Data Needed for Working with Arrays

Type of Data

Filing Cabinet Analogy

Acceptable Values

The array elements

Each element is like the contents of one file drawer

Any valid expression

An index for each element

A numbered label on each file drawer

Any expression that resolves to an integer from to Number.MAX_VALUE inclusive

A data container for the whole array

A label for the entire filing cabinet

A variable, array element, or object property that refers to the array


An array element can contain any simple or composite data item: a number, string, Boolean, function, object, or array. Any valid expression can be used to define an element of an array.

NOTE

An expression is an ActionScript phrase that resolves to a single datum.


A single array can contain data items of various types.

An index can be any non-negative integer, or any expression that resolves to a non-negative integer. The highest valid index is Number.MAX_VALUE . If you go over Number.MAX_VALUE , Flash uses Number.MAX_VALUE as the index.

NOTE

Number.MAX_VALUE is the largest number that ActionScript can represent (1.79769313486231e+308).


The data container that allows you to reference the entire array as a single object can be a variable, array element, or object property.

Creating Arrays

You can create arrays in two ways: using an array literal and using the Array() constructor function with the new keyword.

Here's the format using an array literal:

  container  = [  expression1, expression2, expression3  ]; 

In the preceding format example, container is the variable, array element, or object property that references the entire array, and the expressions inside the square brackets are the expressions defining the elements of the array. Here are some examples:

 var myArray:Array = ["John", "Mary", "Peter", "Pat"]; // container is a variable var students:Object = new Object(); students.scores = [98, 95, 87, 65]; // container is an object property var myMixedArray:Array = ["John", 98, "Mary", 95]; // array, mixed data types 

You can create an array in three ways, using the Array() constructor function:

  • You can call the constructor with no arguments:

     myArray:Array = new Array(); 

    This approach creates an empty array. Do this when you want to define the elements later.

  • You can call the Array() constructor function with a single numeric argument:

     myArray:Array = new Array(8); 

    All that actually happens here is that the array's length property is set to the number you specify. This approach has the effect of creating an array with the specified number of elements, each of which has the value undefined . However, an empty array also returns undefined for any element you reference, so only the length property of the array distinguishes an empty array (no elements) from an array of empty elements (undefined elements).

  • You can call the Array() constructor function with arguments that provide values for array elements. The first argument becomes the value of the first element in the array. The second argument becomes the value of the second element in the array, and so on. For example:

     myArray:Array = new Array(8, 10, 12); myArray:Array = new Array("John", "Matt", "Mary", myVar, myArray, myObj) ; 

If the Array() constructor function sees just one numeric argument, it assumes method 2 and sets the length property. If it sees one non-numeric argument or multiple arguments, it uses the arguments as values for array elements (method 3).

Referencing Array Elements

You use the index to reference array elements. The format is as follows :

  container  [  index  ] 

Thus, the first element in myArray is myArray[0] , the second element is myArray[1] , and so on.

You can both read and write array elements using this format. Here are some examples of reading:

 myVar = myArray[2]; // read the element into a variable myObj.myProp = myArray[6]; // read the element into an object property 

Here are some examples of writing:

 myArray[2] = myVar; // write the variable into the element myArray[6] = myObj.myProp; // write the object property into the element 

Here's an example of reading from one array and writing into another:

 myArray[3] = myOtherArray[0]; 

The fact that you can reference array elements using numbers gives arrays much of their power. A common technique is to use an index variable and the array's length property to set up a for loop that searches through all the elements in the array, tests each one in some way, and takes an action based on the result of that test. The following example searches through an array of names , testing each name to see whether it equals a particular name , and then replaces that name after finding it:

 var nameArray:Array = new Array("John Jones", "Mary Peterson", "Michael Smith"); for (var i:Number = 0; i < nameArray.length ; i++) { // the setup      if (nameArray[i] == "Mary Peterson") {  // the test           nameArray[i] = "Mary Laliberte"; // the action based on the test  } } 

Notice that you need to say i < nameArray.length , not i <= nameArray.length ("less than" not "less than or equal to"), because the last index in an array is one less than the array's length property.

If you have a particular array operation that you perform more than once, you can reduce it to a function. For instance, you could turn the "search and replace" operation shown in the previous example into a function like this:

 function searchAndReplace(inThisArray, findThis, replaceWithThis) {      for (var i:Number = 0; i < inThisArray.length ; i++) { // the setup           if (inThisArray [i] == findThis) {  // the test           inThisArray[i] = replaceWithThis; // the action based on the test      } } 

The var keyword in var i:Number = 0; makes i a local variable to the searchAndReplace() function, preventing it from interfering with other uses of i as a variable elsewhere in the program.

For more information on the var keyword, see "Using var to Create Local Function Variables ," page 488 , in Chapter 20.


Adding Array Elements

You can add a new element to an array just by assigning a value to it. The following example creates an empty array and then adds an element at index position 4:

 myArray = new Array(); myArray[4] = "testing"; 

This also sets myArray.length to 5.

The preceding example illustrates a sparse array, an array in which elements with values are interspersed among elements to which no value has been assigned. Flash allocates memory only for elements with assigned values. Thus, Flash imposes no penalty for using sparse arrays.

As illustrated in the previous section, the same syntax used for adding an element to an array also replaces an existing element at the specified index position.

Removing Array Elements

When removing an array element in the middle of an array, you want to accomplish these two goals:

  • Change the value of the element to undefined .

  • Deallocate the memory previously used to store the value in the element.

The delete operator takes care of both tasks. For instance:

 delete myArray[6]; 

When removing the last element in an array, you want to perform both of these tasks and probably also reduce the length property of the array by one. You can accomplish all three objectives using the pop() method of the Array class:

 myArray.pop(); // deletes last element, decrements length 

The pop() method also returns the value of the element deleted.

For more details on the pop() method, see "pop() and push()," later in this section, under "Array Methods ," page 564.


Named Array Elements: Associative Arrays

An array is actually an object in thin disguise. One result is that arrays can have named properties, just as objects can. An array with named properties is an associative array or hash .

You can assign or retrieve named properties in an array in two ways: using a string in the square brackets, or using the dot operator and an identifier. The following example shows two ways to define a property named "Mary" in the myPhones array:

 myPhones ["Mary"] = "555-555-1212"; myPhones.Mary = "555-555-1212"; 

Similarly, you can retrieve the property using either syntax:

 trace(myPhones ["Mary"]); // 555-555-1212 trace(myPhones.Mary); // 555-555-1212 

You can mix and match these two approaches. For instance, a property defined with a string can be retrieved using the dot operator. The property name must be a legal identifier, or an expression that yields a legal identifier, for both approaches. With the first approach, you supply the identifier as a string; in the second approach, as an identifier.

You can remove named properties using the delete operator. For instance, either of the following statements removes the property named "Mary" and deallocates the memory associated with it:

 delete myPhones["Mary"]; delete myPhones.Mary; 

The length property of an array does not reflect any named properties. An array to which you have added 100 named properties but no numbered properties still has a length of 0. In addition, the array methods, such as push() and pop() , discussed in the next section, do not work with named array properties.

You can access the named properties of an array, like the properties of any object, using a for-in loop.

The for-in loop is covered in "The for-in Statement," page 485 , in Chapter 20.


By the way, you can also give an object numbered properties, as in this example:

 myObj = new Object(); myObj[0] = "hello world"; 

However, assigning numbered properties does not make myObj an array. For instance, myObj still doesn't have a length property or work with the Array methods.

Array Methods

In addition to its length attribute, the Array class has 12 methods of its own: concat() , join() , pop() , push() , reverse() , shift() , slice() , sort () , sortOn() , splice() , unshift() , and toString() . All Array properties are listed in Table 21.4. In addition, it inherits the methods of the Object class.

Table 21.4. Array Methods and Attributes

Name

Method/Attribute

Syntax

Description

concat

M

myArray.concat ( value0,value1 ,... valueN )

Concatenates the arguments and returns them as a new array.

join

M

myArray.join([ separator ])

Joins all elements of an array into a string.

pop

M

myArray.pop()

Removes the last element of an array and returns its value.

push

M

myArray.push( value0,value1 ,... valueN )

Adds one or more elements to the end of an array and returns the array's new length.

reverse

M

myArray.reverse()

Reverses the direction of an array.

shift

M

myArray.shift()

Removes the first element from an array and returns its value.

slice

M

myArray.slice( startIndex, endIndex )

Extracts a section of an array and returns it as a new array.

sort

M

my_array .sort()

Sorts an array in place.

 

M

myArray.sort([compareFunction])

 
 

M

my_array.sort(option option ...)

 
 

M

my_array.sort(compareFunction,option option ...)

 

sortOn

M

myArray.sortOn( fieldName )

Sorts an array alphabetically based on a field in the array.

 

M

my_array .sortOn(" fieldName ", option option ...)

 
 

M

my_array .sortOn([ " fieldName " , " fieldName " , ... ])

 
 

M

my_array .sortOn([ " fieldName " , " fieldName " , ... ] , option option ...)

 

splice

M

myArray.splice( start, deleteCount, value0,value1 ... valueN )

Adds and/or removes elements from an array.

toString

M

myArray.toString()

Returns a string value representing the elements in the Array object.

unshift

M

myArray.unshift( value1,value2 ,... valueN )

Adds one or more elements to the beginning of an array and returns the array's new length.

length

A

myArray.length

The number of elements in the array, including empty or undefined elements.


For more information on the methods of the Object class, see "The Object Class," later in this chapter, page 572 .


join() and toString()

The join() method converts all the elements of an array to strings and concatenates them. That much is exactly the same behavior as the Array.toString() method. However, with the join() method, you can specify a delimiter character or characters to separate the strings. The toString() method doesn't offer the delimiter option.

The format for join() is as follows:

 myArray.join(  delimiter  ); 

If you don't specify a delimiter with join() , Flash uses a comma, exactly duplicating the toString() method. For example:

 myArray = new Array("John", "Matt", "Joe"); names = myArray.join(); 

The output is a string, John,Matt,Joe .

The delimiter option gives you some ability to format the output. For instance, if you want a space after the comma, you can specify a two-character delimiter that consists of a comma and a space:

 myArray = new Array("John", "Matt", "Joe"); names = myArray.join(", "); // names = "John, Matt, Joe" 

The toString() method is used to convert any nested arrays (arrays within the array) to strings. Therefore, these conversions use the simple comma delimiter, not any delimiter that you specify. For example:

 myArray = new Array("John", "Matt", ["Peter","Mary","Sue"],"Joe"); names = myArray.join("--"); // names = "John--Matt--Peter,Mary,Sue--Joe" 

The join() method does not change the array on which it operates.

pop() and push()

The pop() and push() methods treat an array as a stack , and more particularly, a last-in-first-out (LIFO) stack. Imagine a cook stacking pancakes on your plate as they come off the grill. Each time the cook puts one or more pancakes on the stack, that's a push() . When you eat the top pancake on the stack, that's a pop() . In this analogy, the top of the stack of pancakes is the end of the array.

Both of these methods operate on the array in place . That is, they modify the existing array.

The push() method appends one or more new elements to the end of an array. It returns the new length of the array.

When invoked with no arguments, the push() method appends an empty element to the array (one whose value is undefined ). This is equivalent to incrementing the length property of the array by 1.

You can use any expression to determine the value to push onto the array.

The pop() method deletes the last element in an array and returns the value of the element that is deleted. In addition, it decrements the length property of the array.

Here's an example in which we push a value onto an array and then pop it off:

 myArray = new Array(); var x:Number = 3; var y:Number = 4; myArray.push (x + y); myVal = myArray.pop (); trace (myVal) ; 

reverse()

The reverse() method reverses the order of the elements in an array. It does the reversal in place, modifying the existing array. In addition, it returns the reversed array, as shown in this example:

 myArray = new Array (3, 2, 1); returnArray = myArray.reverse(); // myArray is now [1,2,3} trace (returnArray); // 1,2,3 

sort() and sortOn()
graphics/new_icon.jpg

The sort() and sortOn() methods of the Array class gained five new options in Flash MX 2004, giving you more flexibility in how you sort arrays. The options can be referred to by numerals or by constant expressions (strings representing numbers, written in all caps by convention). Table 21.5 shows the five new options.


Table 21.5. New Array Sort Options

Description

Numeral

Constant Expression

Not case sensitive (a precedes Z), rather than case sensitive (Z precedes a).

1

Array. CASEINSENSITIVE

Descending (b precedes a) rather than ascending (a precedes b).

2

Array. DESCENDING .

Limited to arrays in which no two elements have the same sort order, as opposed to sorting any array, even if multiple elements have the same the sort order (and are therefore are placed consecutively in the sorted array in no particular order).

4

Array. UNIQUE

Returns a new array rather than returning nothing and modifying the array in place.

8

Array. RETURNINDEXEDARRAY

Numbers are treated as strings, so 1000 is "lower" than 9, because "1" is a lower string value than "9".

16

Array.NUMERIC


When called with no arguments, the sort() method sorts array elements in alphabetical order, temporarily converting them to strings first, if necessary. Any undefined elements are sorted to the end of the array. Use the Array.NUMERIC option to sort numerically .

To sort on some other basis, you need to provide a comparison function as an argument to the sort() method. The comparison function takes two required arguments. They represent any two elements of the array. It's as if you have been asked, "Given any two elements of this array, which one should come first?" You must answer this question with your comparison function.

The function must return a negative number if the first element should come first in the sorted array. If the second element should appear first, the comparison function must return a positive number. If the comparison function returns , it says that it doesn't matter which element comes first.

In the following example, the byVotes() comparison function sorts an array of objects representing candidates according to which candidate object has the larger number in its votes property. The comparison function returns a positive number if the second object received more votes than the first. Thus, this function effectively says, "Put the object with the most votes first." The same thing could have been accomplished if a negative number were returned if the first object received more votes than the second. The result of the following example is a candidates array with c3 and c2 in the 0 and 1 positions , and c1 and c4 following in no particular order (because they have the same number of votes).

 var c1:Object = {fname: "Bob", lname: "Smith", votes: 2}; var c2:Object = {fname: "Charles", lname: "Boitier", votes: 30}; var c3:Object = {fname: "Dave", lname: "Meeks", votes: 100}; var c4:Object = {fname: "Abbey", lname: "Smith", votes: 2}; var candidates:Array = [c1, c2, c3, c4]; function byVotes (a, b) {     return b.votes - a.votes; } candidates.sort(byVotes); 

The sortOn() method provides a more concise notation for sorting objects in an array based on the value of a property of each object, eliminating the necessity for a comparison function. Prior to Flash MX 2004, sortOn() would not work in the previous example because sortOn() was limited to alphabetic sorting. Now, however, you can use the numeric option to make it sort numerically. So this single line accomplishes the same thing as the previous example:

 candidates.sortOn("votes", Array.NUMERIC); 

You can use an array of field names, for primary and secondary sorts. For instance, sorting on last name and first name:

 candidates.sortOn(["lname", "fname"]); 

concat()

The concat() method appends one or more values to an array. It returns a new array rather than modifying an existing array. For example:

 myArray = new Array (3, 2, 1); myArray.concat(4,5,6); //  returns [3,2,1,4,5,6] 

If one of the arguments is an array, it will be "flattened" and appended. Therefore, the following has the same result as the previous example:

 myArray = new Array (3, 2, 1); myArray.concat(4, [5,6]); //  returns [3,2,1,4,5,6] 

Nested arrays, however, are not flattened:

 myArray.concat([ 4, [5,6] ]); //  returns [3,2,1,4,[5,6] ] 

slice()

The slice() method returns a new array that is a "slice" or subarray of the original array. It does not change the original array. The slice() method takes two arguments: The first specifies the index of the first element to be returned, and the second is one greater than the index of the last element to be returned. If you provide only one argument, the slice contains all the elements of the array, starting at the index position indicated by the argument. A negative argument indicates an index position relative to the end of the array, starting with -1 for the last element in the array. Here are some examples:

 myArray = [1,2,3,4,5,6]; myArray.slice(1,2); // 2 myArray.slice(1,-1); // 2,3,4,5 myArray.slice(0,3); // 1,2, 3 

splice()

The splice() method can be used to add, remove, or both add and remove elements in a single operation. It modifies an existing array rather than returning a new array.

The format for the splice() method is as follows:

 myArray.splice(  startIndex, deleteCount, value0,value1  ...  valueN  ) 

All arguments except the first are optional. With only the startIndex argument, it deletes all elements beginning with startIndex . It returns the deleted elements. For instance:

 myArray = [1,2,3,4,5,6]; trace(myArray.splice(1)); // returns : 2,3,4,5,6 -- these were deleted trace(myArray); // 1 -- this is all that's left 

The second parameter tells the splice() method how many elements to delete. Remaining elements are shifted downward (toward lower index numbers) to fill the gap. For instance:

 myArray = [1,2,3,4,5,6]; trace(myArray.splice(1,2)); // 2,3 -- it just deleted two elements trace(myArray); // 1,4,5,6 -- leaving four elements in the array 

The rest of the arguments provide values for elements to insert into the array, beginning at the index position following startIndex . Existing elements are shifted upward in the array to accommodate the new elements. For example:

 myArray = [1,2,3,4,5,6]; trace(myArray.splice(1,2,"flowers","teakettles")); // 2,3 - the deleted elements trace(myArray); // 1,flowers,teakettles,4,5,6  the new array 

unshift() and shift()

The unshift() and shift() methods are similar to push() and pop() , except that they insert and remove elements at the beginning of the array rather than at the end .

The unshift() method inserts one or more elements at the beginning of the array and returns the new length. Existing elements are shifted upward. For example:

 myArray = [1,2,3,4,5,6]; trace(myArray.unshift("flowers","teakettles")); // 8 -- the new length trace(myArray); // flowers,teakettles,1,2,3,4,5,6 -- the new array 

The shift() method removes the first element in the array, returning the deleted element. Existing elements are shifted downward to fill the gap. For example:

 myArray = [1,2,3,4,5,6]; trace(myArray.shift()); // 1 -- returns the deleted element trace(myArray); // 2,3,4,5,6 -- here's what's left 

Boolean , Number , and String : The Wrapper Classes

The Boolean , Number , and String classes are "wrapper" classes for the corresponding primitive datatypes. An instance of a wrapper class contains a primitive datum in an inaccessible internal property. Unlike the primitive datum, an instance of a class can have properties and methods, both local and inherited. In the three core wrapper classes, all the built-in methods and properties but one are inherited from the class prototype object. The one exception is the length property of the String class: Obviously, each string needs to have its own length property.

For a complete table of methods and properties of the wrapper classes, see Appendix A, "ActionScript Reference," under "Wrapper Classes: Boolean, Number, String," page 968 .


The Boolean Class

The Boolean class is the simplest class in ActionScript. Instances have just two attributes: __proto__ , which references the class prototype object, and constructor , which references the class constructor function. Every object has these properties. From now on, I usually won't bother to mention them.

The Boolean class has just two methods, which are also inherited from the Object class:

  • toString() returns the Boolean value ( true or false ) as a string.

  • valueOf() returns the primitive Boolean datum, allowing you to compare the values contained in the objects.

Comparing Objects

Two objects do not compare as equal just because they have the same properties with the same values. By default, two object references compare as equal only if they refer to the same object . Flash MX follows the ECMA-262 standard in comparing objects by reference , not by value . For instance, here we have two Number objects, both with the value 1, but they don't compare as equal:

 trace(a == b); // false 

For Boolean , Date , Number , and String objects, you must use the valueOf() method to compare their contents:

 trace(a.valueOf() == b.valueOf()); // true 

For other objects, a specific method may be required to get the values. To compare the colors stored in two instances of the Color class, for instance, you can use getRGB() .


For more details on the distinction between "by reference and "by value," see "Passing Arguments by Value and by Reference," page 490 , in Chapter 20.


The toString() method is seldom needed because ActionScript typically performs automatic conversion to the string datatype when appropriate. It can be used to force the use of a string or just to make absolutely sure that you are dealing with a string. However, the global String() conversion function performs the same task and allows you to use the same format with both objects and primitive data.

For more information on the toString() and valueOf() methods, see "The Object Class," later in this chapter, page 572 .


For more details on the global conversion functions String() , Number() , and Boolean() , see "Explicit and Implicit Data Conversion," page 469 , in Chapter 20.


The Number Class

The Number class has toString() and valueOf() methods, which, respectively, return the string equivalent of the number and the primitive number datum.

In addition, the Number class has five constants: NaN ("not a number"), Number.MAX_VALUE , Number.MIN_VALUE , Number.POSITIVE_INFINITY , and Number.NEGATIVE_INFINITY .

The Number constants are discussed under "Number," page 465 in Chapter 20.


The String Class

The String class has a valueOf() method, which returns the primitive string datum. Each member of the String class has an instance attribute, length . In addition, the String class has a dozen string manipulation methods, which are among the most frequently used in ActionScript. They are also among the most processor- intensive , inspiring programmers to write alternative optimized methods.

String methods can be divided into four categories: searching for a character or character sequence, retrieving a portion or portions of a string, converting to lower- or uppercase, and generating characters from character codes or vice versa.

The String.split() method splits a string into substrings. The first argument, delimiter , is the character string that marks the places to make the splits. When the delimiter is the empty string, String.split() returns an array in which each element is one character in the string. For instance:

 var myString:String = "Joe"; var i = myString.split(""); trace (i); // J,o,e trace (i.length); // 3 

An optional second argument, limit , specifies the maximum number of substrings.

The String.substring() method returns a substring starting at startIndex and ending one character before endIndex . The Flash 6 Player introduced a bug into this method. If startIndex is greater than endIndex , the Flash interpreter swaps them before running the function. However, startIndex must always be less than the length of the string. If it is equal to the length or greater, there's no swapping, and the empty string is returned.

The Date Class

The Date class allows you to determine the current time and date and store times and dates in objects. All times and dates in ActionScript are stored in the form of a single number: the number of milliseconds before or after midnight of January 1, 1970 UTC (Coordinated Universal Time, which is the same as Greenwich Mean Time). This number is returned by the Date.valueOf() method.

You can use Date class methods to get and set the date/time as a single object, or to get and set the year, month, date, day, hour , minute, second, and millisecond independently, in local or UTC time. You can also retrieve the number of minutes between UTC and local time by using getTimezoneOffset() .

There is also a toString() method, which returns full date information in a human-readable form like the following: Sun Jun 16 18:04:58 GMT-0600 2002 . The Date() global function does the same thing: myDate.toString() yields the same result as Date(myDate) . Neither is needed very often because of automatic datatype conversion.

For a listing of Date methods, see Appendix A, under "Methods of the Date Class," page 951 .


You can use the Date constructor in three ways:

  • myDate = new Date(); sets myDate to the current date and time.

  • myDate = new Date(1000000); sets myDate to the date and time one million milliseconds after midnight of January 1, 1970.

  • myDate = new Date(2004, 1, 2, 3, 4, 5, 6); sets myDate to January 2, 2004, at 3:04 a.m., plus 5 seconds and 6 milliseconds. Thus, the format is new Date ( year, month, date, hour, minute, second, millisecond ); .

In the last format, all parameters except year and month are optional and are set to zero if not supplied. Hours are set on a 24-hour clock, where midnight is 0 and noon is 12. For the year, a value of 0 to 99 indicates 1900 though 1999. For years beyond 1999, you need to specify all four digits of the year.

The Error Class

graphics/new_icon.jpg

The Error class, new in Flash MX 2004, is used in conjunction with try/catch/finally and the throw keyword to implement a standard means of error trapping in Flash MX.


The try/catch/finally statement is introduced in Chapter 20, under "The try/catch/finally Statement," page 482 .


It's a simple class, with two attributes and one method:

  • message ” The error message, a string

  • name ” A name you assign to the error class, a string

  • toString() ” A method that returns message

Both message and name default to "Error".

Here's a fully functional example (tryCatch.fla on the CD), in which an error condition is simulated in the getCustomerInfo() function by a return value of 1. (The idea is that the function would return to 0 if all went well, but we're only simulating the error condition here.)

 1:  function getCustomerInfo() { return (1); } 2:  try { 3:    var returnVal = getCustomerInfo(); 4:    if(returnVal != 0) { 5:      throw new Error("Error getting Customer information."); 6:    } 7:  } catch (e) { 8:    trace(e.name+" : "+e); // error processing goes here 9:  } 10: finally {trace("finally")}; // "clean-up" or other final actions 

Line 1 simulates an error condition by returning 1. Within the try block, line 4 tests for an error return (any return other than 0). The throw statement on line 5 is where the Error class comes in. The new Error object will have the text string "Error getting Customer information." as its message attribute. The Error object is "caught" on line 7. On line 8, the trace statement displays the Error object's name attribute ("Error" in this case). Also on line 8, displaying the Error object itself (the e at the end of the trace statement) automatically invokes the Error object's toString() method, displaying the message value in the Output window.

You can create different error classes by subclassing the Error class, like this:

 // CustErrorNoSuchCust.as class CustErrorNoSuchCust extends Error {     private var name:String = "NoSuchCustomer";     private var message:String =         "Error getting Customer information: No such customer."; } // CustErrorInactiveAcct.as class CustErrorInactiveAcct extends Error {     private var name:String = "InactiveAcct";     private var message:String =         "Error getting Customer information: Inactive Account."; } 

Notice that you can make name and message private, and you will still be able to access them, because you are inheriting get/set methods from the Error class.

In a real application, getCustomerInfo() would be a method of a class, such as a Customer class. Here's a minimal version, hard-coded for this example to return the "no such customer" error:

 //Customer.as class Customer {     private var noSuchCustomerCondition:Boolean = true;     private var inactiveAcctCondition:Boolean = false;     function getCustomerInfo() {       if (noSuchCustomerCondition) {         throw new CustErrorNoSuchCust();       }       if (inactiveAcctCondition) {         throw new CustErrorInactiveAcct();       }     } } 

Then the .fla looks like this:

 // tryCatch2.fla var myCustomer:Customer = new Customer (); try {     myCustomer.getCustomerInfo();   } catch (e:CustErrorNoSuchCust) {     trace(e.name+" : "+e.toString());     // more processing specific to the "no such customer" error  } catch (e:CustErrorInactiveAcct) {     trace(e.name+" : "+e.toString());     // more processing specific to the "inactive account" error   } finally {trace("finally")}; // "clean-up" or other final actions 

All the files for the preceding example are available on the CD, with the names indicated in the comment at the top of each section of code.

The Function Class

The Function class is a "nonconstructive" constructor: You can't create usable new instances with the new keyword. The Function class has just two built-in methods: apply() and call() .

The apply() and call() methods, as well as the syntax for creating a function, are covered in "Combining Statements into Functions," in Chapter 20, page 486 .


The Object Class

The Object class is the foundation for all other classes in ActionScript. All other classes inherit from it and thus share its properties and methods. An instance property assigned by this class, and therefore present in every ActionScript object, is __proto__ , which points to the prototype of the object's class.

The Object class has 11 properties, all hidden by default. You can use the undocumented ASSetPropFlags() function to "unhide" 10 properties of the Object class:

 ASSetPropFlags(Object.prototype, null, 8, 1); for (a in Object.prototype) trace (a); 

The 10 properties are constructor , isPropertyEnumerable() , isPrototypeOf() , hasOwnProperty() , toLocaleString() , toString() , valueOf() , addProperty() , unwatch() , and watch() . Every object created with the new operator inherits these properties, the last 9 of which are methods.

The eleventh property is the registerClass() method, which is not covered here because it is used only in AS1, not in AS2.

Object properties are summarized in Table 21.6.

Table 21.6. Methods and Attributes of the Object Class

Name

Method/Attribute

Format

Description

addProperty

M

myObject.addProperty ("myProp", getMyProp, setMyProp)

Creates a getter/setter property named myProp .

constructor

A

myObject.constructor

Points to the constructor function of the class.

hasOwnProperty

M

myObject.hasOwnProperty("myProp")

Returns true if myObject has an instance property named myProp ; otherwise , returns false .

isPropertyEnumerable

M

isPropertyEnumerable( property )

Returns true if property is an instance property that would be enumerated by a for-in loop.

isPrototypeOf

M

protoObject .isPrototypeOf( instanceObject )

Returns true if instanceObject uses protoObject as the prototype object from which it gets shared properties. Otherwise, it returns false .

registerClass

M

Object.registerClass ("linkageID", MyClass);

Preregisters a movie clip for membership in a class.

toLocaleString

M

myObject.toLocaleString()

Returns a string appropriate to a particular country or area; by default, returns the string [object Object] .

toString

M

myObject.toString()

Returns the string [object Object] .

unwatch

M

See Table 21.8

Removes the registration that a watch() method created.

valueOf

M

myObject.valueOf()

In the Object class, returns the object itself by default. Child classes, such as Boolean , Date , Number , and String , may define more useful valueOf() methods.

watch

M

See Table 21.8

Registers a callback function to be invoked when a specified property of an object changes.


Undocumented properties are constructor , isPropertyEnumerable() , isPrototypeOf() , hasOwnProperty() and toLocaleString() . The behavior of any undocumented feature is subject to change in future versions of Flash. However, of the eleven properties of the Object class, seven are defined in the ECMA-262 standard and are also found in JavaScript. (Though both have propertyIsEnumerable() , not isPropertyEnumerable() .) The four properties that are Flash-specific are addProperty() , registerClass() , unwatch() , and watch() .

constructor

The purpose of the constructor property is to point to the constructor function of the class. The constructor property can therefore be used to determine an object's class:

 mySound = new Sound(); if ((typeof mySound == "object") && (mySound.constructor == Sound))      // then do something with the Sound object 

Each instance of the class has its own local constructor property, and the prototype object of the class (like any other object) also has a constructor property.

toString()

The purpose of the toString() method is to return a string that represents the object in some manner. ActionScript invokes this method when it needs to convert an object into a string. Some built-in objects come with class-specific toString() methods. They are listed in Table 21.7.

Table 21.7. Return Values of toString() Methods of Built-in Objects

Class

Return Value of toString() Method

Array

A comma-separated list of the array's elements converted to strings

Boolean

true or false as a string

Date

The full date and time in the form Sun Jun 16 18:04:58 GMT-0600 2002 ( [*] )

Button , MovieClip , TextField

The absolute path to the instance

Number

The number as a string

Object

The string [object Object]

XML node object or XML document

XML source code


[*] GMT is the Greenwich Mean Time (same as UTC) offset.

Classes that do not have class-specific toString() methods use the one they inherit from the Object class, which returns the string [object Object] . You can assign a class-specific toString() method to get a more meaningful return, as in this example:

 Sound.prototype.toString = function () {return "Sound";}; 

When you create a class, you may want to create a toString() method that will return information that you can use either for debugging or in your program.

toLocaleString()

The toLocaleString() method is an alternate, implementation-specific version of the toString() method. Its purpose is to provide a localized version of the string representing the object. Localization refers to adapting to various countries and languages. The toLocaleString() method in the Object class prototype returns the same thing as the toString() method. However, you can define toLocaleString() methods for built-in classes.

isPropertyEnumerable()

The isPropertyEnumerable() method takes one argument, which is a property of the object, and returns true for instance properties that would be enumerated by a for-in loop. If the property does not exist, if it is not an instance property, or if it would not be enumerated by a for-in loop, isPropertyEnumerable() returns false .

isPrototypeOf()

The isPrototypeOf() method takes one argument, which is an object. The format is as follows:

  protoObject  .isPrototypeOf(  instanceObject  ); 

If instanceObject uses protoObject as the prototype object from which it gets shared properties, isPrototypeOf() returns true . Otherwise, it returns false . The isPrototypeOf() method depends on the __proto__ property of the instance object to find the instance object's prototype.

valueOf()

Just as the toString() method represents the object as a string, the valueOf() method represents the object as another primitive datatype. The default valueOf() method in the Object class returns the object itself ”which is something like buying a dollar bill for a dollar. However, a class can define a useful valueOf() method. For instance, the Date class has a valueOf() method that returns the number of milliseconds between the time of the Date object and midnight, January 1, 1970. For dates prior to that time, the number is negative. (This method is equivalent to the Date.getTime() method.)

 myDate = new Date(); trace (myDate.valueOf()); // 1024275924859 trace (myDate); // Sun Jun 16 18:05:24 GMT-0700 2002 

The Boolean , Date , Number , and String classes define valueOf() methods that return the primitive datum, allowing you to compare these primitive values.

hasOwnProperty()

The hasOwnProperty() method takes one string argument specifying a name of a possible local property. The method returns true if the object has an instance property with that name. Otherwise, it returns false . The format looks like this:

 myTextField.hasOwnProperty("myProp") 

findValueOf.fla on the CD accompanying this book creates a global findValueOf() function, using the hasOwnProperty() method to determine whether an object or any of the prototype objects it inherits from has a valueOf() method.

addProperty()

The addProperty() method makes it easier to use get/set functions with ActionScript 1. In external class files (with AS2), you can use get or set instead.

The addProperty() method allows you to add a property and associate get/set functions with it in one step. Thereafter, the dot syntax will actually call the get/set functions.

The format of the addProperty() method is as follows:

 myObj.addProperty("myProp", getMyProp, setMyProp) 

Instead of the names of get and set functions, you can use function literals, as shown in sample movie addpropliteral.fla on the CD.

For more information, see addProperty.htm on the CD.

watch() and unwatch()

The watch() and unwatch() methods register and unregister a callback function that is called whenever an attempt is made to change a particular property. This is a powerful capability, but one that comes at a cost: If you watch a property that is constantly changing, the callback function fires constantly, creating an excessive processing load.

The watch() method is useful for debugging. It can also be used as a kind of general-purpose event generator, like an addListener() for changes in properties. However, you can have only one watchpoint at a time on any given property. If you set a second watchpoint , it replaces the previous one. This contrasts with listeners: You can have as many listeners as you want for any given event. With watch() , you could implement your own event model so that any number of objects could "get the news" when the property changes.

The watch() method is not recommended for use with getter/setter properties. Although it may work to some extent, it could miss some changes, and there is a potential for creating excessive processing loads. Most built-in properties are getter/setter properties.

To start to watch a property, take these two steps: Define a callback function and execute the watch() statement. Table 21.8 shows formats for both steps, as well as the format for terminating the watch() with unwatch() .

Table 21.8. watch , callback , and unwatch

Method/Function

Format

Parameters

watch

myObj.watch( property , callback , userData );

property Specifies the property to watch (a string)

callback Specifies a callback function (a reference)

userData (optional) ” Specifies data to be sentto the callback function

callback function

function myFunc ( property , oldval , newval , userData ) { // statements }

property Contains the propertythat changed

oldval Contains the previous value of property

newval Contains the new value of property

userData Contains data defined in the userData parameter of the watch() statement

unwatch

myObj.unwatch ( property );

property Specifies the property to stop watching


Both watch() and unwatch() return true if successful; otherwise, they return false .

The callback function is invoked as a method of the object containing the watched property (such as myObj in Table 21.8). Inside the callback function, this refers to myObj .

The object, such as myObj , that contains the property to be watched must exist when you set the watchpoint, and the watchpoint disappears if you delete the object. However, the watchpoint exists independently of the property it is watching. You can create a watchpoint on a property that does not yet exist, and the watchpoint will go into effect when you create the property. Similarly, you can delete a property for which a watchpoint has been set without destroying the watchpoint. If you later re-create the property, the watchpoint will still be in effect. To remove a watchpoint without deleting the object, use the unwatch() method.

The sample movie watch.fla contains a statusObj object with a property named isOkay :

 statusObj = new Object(); statusObj.isOkay = "okay"; 

The following line sets a watchpoint on the isOkay property:

 statusObj.watch("isOkay", setStatusText); 

The callback function setStatusText() is as follows (I omitted the fourth parameter, userData , because it's not used):

 function setStatusText (prop, oldval, newVal) {      statusField.text = newVal;      if (newVal == "okay") {           statusField.setTextFormat(okayFormat);      }      else {           statusField.setTextFormat(errorFormat);      } } 

If the new value for the isOkay property is "okay" , the status field text format is set to the okayFormat . If the new value for the isOkay property is anything other than "okay" , the status field text format is set to the errorFormat .

The callback function is triggered by an attempted change in a property value. However, any actual change in that property is under the control of the callback function. If the callback function does not return a value, the property value is set to undefined . This is always the case with the setStatusText() function just shown, for instance. It never returns anything, so the watched property is always undefined .

If the callback function does return a value, the property is set to the return value. Because the callback function gets the previous value as its second parameter, it can nullify the change simply by returning the previous value. The watch() method's capability to control the value of the property or nullify the change distinguishes it from the addProperty() method.

The Math Object

Math is not actually a class but a singleton, that is, an instance of a class that can have only one instance.

Often, mathematical functions are the most straightforward way to achieve a desired motion or effect, whether smooth and natural or wildly and wonderfully unnatural . In addition, Math functions are often more flexible than any other approach, including tweening; that is, you can accomplish a broader range of tasks with them.

NOTE

Combining the drawing methods and the math methods can yield marvelous results. On the CD, see drawing.htm and examples from Keith Peters (3Dcube.fla and test5.fla) and Millie Maruani (api_flower.fla and api_cube.fla).


The Math object has enough methods with varied uses to fill a book by itself. I'll give examples of some of the most common methods and some of the most powerful ones.

For a full listing of math functions, see "Math Methods and Attributes" in Appendix A, page 957 .


Common Math Functions

Among the most commonly used methods of the Math object are floor() , random() , and round() .

floor()

The floor() method truncates a decimal number and returns just the integer portion. For example:

 x = Math.floor (8.21) // result: 8 x = Math.floor (8.5) // result: 8 x = Math.floor (-8.21) // result: -9 x = Math.floor (-8.5) // result: -9 

random()

The random() method returns a decimal number greater than or equal to and less than 1 , usually with 14 to 17 digits. For example:

 x = Math.random(); /* Sample results: 0.236938397510414 0.102950482211518 0.274189059284604 0.585484127786702 0.00277895387391511 0.80261959452304 */ 

round()

The round() method rounds a decimal number to the nearest integer. Here are some examples:

 x = Math.round (8.21) // result: 8 x = Math.round (8.5) // result: 9 x = Math.round (8.6) // result: 9 x = Math.round (-8.21) // result: -8 x = Math.round (-8.5) // result: -8 x = Math.round (-8.6) // result: -9 

In the following example, mcPercent is the integer percent of myClip that has been loaded:

 mcPercent = Math.round((myClip.getBytesLoaded() / myClip.getBytesTotal()) * 100); 

To round decimal fractions, first multiply by a power of 10, round, and then divide by the same power of 10. The power of 10 you use determines the number of decimal places you round to. For instance, the following example rounds y to one decimal place:

 y = .12; yr = Math.round(10*y)/10; // yr is .1 

In the preceding example, if y is any positive decimal fraction, yr will be 0.0 , 0.1 , 0.2 , 0.3 , 0.4 , 0.5 , 0.6 , 0.7 , 0.8 , 0.9 , or 1.0 .

Generating a Random Integer from 0 to 9, Inclusive

You can combine random() and round() to produce random integers. This code executes the steps one by one:

 for (i = 0; i < 10; i++) {      x = Math.random(); // generate random number less than 1      x *= 10; // multiply by 10      x = Math.round(x); // round off      trace(x); } 

Here's a shorter, faster form, replacing the whole body of the preceding for loop:

 trace(Math.round(Math.random()*10)); 

Using Math.sqrt() to Get and Set Relative Positioning

The Math.sqrt() (square root) method can be used both to determine and to control the position of one movie clip relative to another, or relative to any known point on the Stage. For instance, Math.sqrt() can be used to keep a draggable movie clip a fixed distance from a point, thus constraining the clip's movement to an arc.

This use of the Math.sqrt() method to control position is founded on the fact that the position of a movie clip on the Stage is completely determined by two numbers: its x position and its y position. Therefore, you can constrain a draggable clip to any path if you can come up with a formula that will give you one of these numbers if you have the other.

In Figure 21.2, if I give you an x position within the range of the arc, you can tell at a glance what y position you would have to assign to the mouse to keep it on the arc.

Figure 21.2. The Math.sqrt() function keeps the mouse a constant distance from the center point of the arc, thus keeping it on the arc.

graphics/21fig02.gif


So perhaps it's not surprising that there is a mathematical equation that can do the same thing. By putting this equation into the mouse movie clip's enter frame event handler, you can force the mouse onto the arc in every frame where the x position permits it. This technique is demonstrated in sample movie constrain.fla.

The equation gets the mouse's _x property and then sets its _y property appropriately. The equation uses the fact that every point on the arc is the same distance from the center of the arc, namely, half the width of the arc movie clip. This distance is the radius of the arc, r in the formula. Here's the ActionScript:

 onClipEvent(load){      var r = root.arc._width/2; // the radius of the arc      var ctr_x = 400; // the x position of the arc's center      var ctr_y = 300; // the y position of the arc's center } onClipEvent(enterFrame) {  y = Math.sqrt((r * r  ) - ((_x  ctr_x) * (_x  ctr_x))) + ctr_y; } 

How was the formula derived?

Start from the fact that the distance between any two points on the Stage can be reduced to an x difference and a y difference. For example, in Figure 21.2, to get from the mouse to the center of the half circle, instead of going directly, you could go up (the y difference) and then left (the x difference).

Similarly, if you're given the x and y differences, the direct route is obvious. These three distances form a triangle, and given any two sides of a triangle, the third one is always obvious. Mathematically, if you know the direct distance from the mouse to the center of the arc and the x difference from the mouse to the center of the arc, you can calculate the y difference.

In this case, the distance from the mouse to the center of the arc is the radius of the arc, r ; it is half the width of the arc movie clip ( arc._width / 2 ). The x difference is _x minus ctr_x , _x being the x position of the mouse (you don't have to specify the movie clip instance name because the code is inside the mouse event handler), and ctr_x being the x position of the center point of the arc. Similarly, the y difference is _y minus ctr_y .

The equation that gives you the y difference is a form of the Pythagorean theorem , which says that y 2 = r 2 - x 2 , where y is the y difference, r is the radius, and x is the x difference.

In ActionScript, the equation is as follows:

 (y  ctr_y) * (y  ctr_y) = r * r  (x  ctr_x) * (x  ctr_x); 

Taking the square root of both sides, you get the following:

 y  ctr_y = Math.sqrt (r * r - (x  ctr_x) * (x  ctr_x)); 

Adding ctr_y to both sides gives the desired formula:

 y = Math.sqrt((r * r) - ((_x  ctr_x) * (_x  ctr_x))) + ctr_y; 

Basic Trig Methods: Math.sin() and Math.cos()

The trigonometry methods, of which the most commonly used are sine ( Math.sin ) and cosine ( Math.cos ), are perhaps the most versatile methods of the Math object. These are demonstrated in several .fla files on the CD. For instance, sample movie treeshadow.fla uses the _rotation property of a movie clip to make a "tree" topple, and animates its lengthening shadow as it falls , using the cosine ( Math.cos ) method, while calculating how far the top of the tree is from the ground, using the sine ( Math.sin ) method.

Sample movie enemy.fla uses trig to determine whether a gun is pointing at an enemy. You could use a similar approach to determine how many degrees ( _rotation ) to open a monster's jaws to accept an object of a given size .

The triangle in the circle on the left side of Figure 21.3 provides a visual representation of the sine and cosine functions. The sample movie, Helen Triolo's trigdemo.fla, brings it to life: On the left side of the figure, the sine and cosine functions are shown as legs of a triangle in a "unit circle," in which radius r is one unit in length. The radius is the hypotenuse (longest leg) of the triangle. The radius and the horizontal leg of the triangle form an angle, [ Q ] (theta) . As the radius rotates around the circle, the horizontal leg of the triangle is the cosine, and the vertical leg is the sine, of the angle [theta] (theta). On the right side of the figure, you see how the sine function, in going up and down, traces a sine wave over time.

Figure 21.3. A screenshot from trigdemo.fla. (Source: Helen Triolo)

graphics/21fig03.jpg


Officially, the sine is the ratio of the vertical leg to the hypotenuse ( y/r ), but if the hypotenuse measures one unit ( r = 1 ), then y/r is just y . Similarly, the cosine is the horizontal leg over the hypotenuse ( x/r ), which equals x if r equals 1.

CAUTION

Flash measures _rotation clockwise , whereas the unit circle assumes counterclockwise rotation. You can reverse Flash's natural rotation direction to get it to match trigonometry functions better.


CAUTION

The unit circle assumes that zero degrees rotation is at 3 o'clock on the circle. Zero degrees rotation for a movie clip is whatever position it starts in. If a movie clip representing a tree starts with the tree upright, the tree will point to 90 ° (12 o'clock) on the unit circle when its _rotation is zero degrees.


By visualizing your movies within this unit circle, you can see how to produce the effects mentioned in the first paragraph of this section. See trigdemo.fla and trigdemo.htm on the CD for more details.

Using Trig to Get and Set Width and Height

Sample movie treeshadow.fla uses the _rotation property of a movie clip to make a "tree" topple, as shown in Figure 21.4, and animates the tree's lengthening shadow as it falls, using the cosine ( Math.cos ) method, while calculating how far the top of the tree is from the ground, using the sine ( Math.sin ) method.

Figure 21.4. Using trig to lengthen a shadow and measure distance from the ground.
graphics/21fig04.jpg

The toppling tree is the radius rotating ( treeHeight in the program). This happens to be the width of the tree movie clip because the tree starts out lying down horizontally on the Stage. The shadow the tree casts is the cosine. The decreasing distance from the top of the tree to the ground as it falls is the sine.

Because this is not a unit circle ( treeHeight is not equal to 1 ), you have to divide the horizontal leg of the triangle by the radius ( treeHeight ) to get the cosine. So, when the tree has fallen halfway to the ground (45 °), you get

 shadow / treeHeight = cos(45) 

Multiplying both sides by the length of the tree, you get

 shadow = cos(45) * treeHeight 

The following line from sample movie treeshadow.fla uses shadow._xscale instead of an absolute value for setting the shadow width. However, because the _root.shadow clip is 100 pixels wide, setting its _xscale is the same as setting its _width . (See "Sizing Clips via Scale Instead of Height and Width," in trigdemo.htm on the CD.) The following code also converts the rotation measurement from degrees to radians for use by the cosine function:

 _root.shadow._xscale = Math.cos(deg2rad(_root.tree._rotation))*treeHeight; 

Radians and Degrees

In ActionScript, the trigonometry functions require angle measurements in radians . If you prefer to work in degrees, use a function that translates degrees into radians. The formula is

  radians  =  degrees  * pi / 180 

Thus, in the sample movie, treeshadow.fla, to find the cosine of the rotation of a falling tree, you use

 function deg2rad(degrees) {      return degrees * Math.PI/180; } Math.cos(_root.deg2rad(_root.tree._rotation) 

Table 21.9 gives some examples of rotation measurements in degrees and their radian equivalents.


NOTE

The number pi ([ ]), represented in ActionScript by Math.PI , is the ratio of the circumference to the diameter of a circle, approximately 3.14.


Table 21.9. Degrees and Radians

Degrees

Radians

Full circle (360)

2 * Math.PI

Half circle (180)

Math.PI

Quarter circle (90)

Math.PI/2

Eighth circle (45)

Math.PI / 4


Similarly, the sine is the vertical distance divided by the radius, so you can start with

  distance from ground  / treeHeight = sin(45) 

Multiplying both sides by the length of the tree, you get

  distance from ground  = treeHeight * sin(45) 

The sample movie rounds off the distance to display it more easily. It also uses Math.abs to take the absolute value, to compensate for Flash's reversed rotation direction. Finally, it subtracts 1 , which causes it to round to instead of rounding to 1 at each extreme of the tree's fall.

 _root.distanceFromGround = Math.round(Math.abs (Math.sin(deg2rad(_root.tree._rotation)) graphics/ccc.gif *_treeHeight)-1) ; 

Using Trig to Get and Set Direction

To determine whether a gun is pointing at an enemy, use the gun's pivot point as the center of the unit circle, as shown in Figure 21.5.

Figure 21.5. Sample movie enemy.fla uses the Math.sin() method to determine when a gun is pointing at any enemy. (Source for robot graphic: Poser 4, Curious Labs. Gremlin source: DAZ Productions.)
graphics/21fig05.gif

The unit is the direct distance from the gun to the enemy. Begin with the gun in a horizontal position and rotate the gun while checking in each frame whether the sine of the rotation equals the y difference between the enemy and the gun:

 if (Math.sin(angle) == y) 

In sample movie enemy.fla, it was necessary to add a couple of extra steps. For one, the movie starts with the gun at a nonzero rotation. The initial rotation is subtracted before the sine is taken. This effectively "zeroes out" the rotation.

 angle = _root.gun._rotation - gunRotationStart; 

Of course, there is the usual translation to radians:

 sinAngle = Math.sin(deg2rad(angle)); 

The final test is completely straightforward:

 if (sinAngle == yr) 

The yr variable in this statement is the y difference between the gun and the enemy, expressed in terms of r :

 var y = _root.gun._y - _root.enemy._y; var yr = Math.round(((10*y) / r))/10; 

Note the rounding of the y distance to one decimal place, using the round() method.

Rounding to one decimal place is discussed in "round()," earlier in this chapter, page 579 .


The sine is similarly rounded:

 sinAngle = Math.round(10*sinAngle)/10; 

Both the sine and the y distance had to be rounded off, or they would never test equal because of minute differences.

Controlling Position with Math.sin()

Using the Math.sin() method, you can vary any property of a movie clip by substituting the property for y in this equation, which represents the general format of the Math.sin() method:

 y = Math.sin(x); 

Figure 21.6 shows the result of moving the butterfly to the right (incrementing the _x property of the movie clip) the same amount in each frame, while moving the butterfly vertically (incrementing or decrementing the _y property of the movie clip) with the Math.sin() function.

Figure 21.6. The Math.sin() method can control position, speed, and rotation to produce natural, gentle transitions and effects. Here, the Math.sin( ) method controls the vertical position of the butterfly. (Human figure produced with Poser 4, Curious Labs.)

graphics/21fig06.gif


In the figure, the dots show the sinuous path followed by the butterfly. Here is the logic of the code controlling the butterfly's movement, expressed in pseudocode:

 onClipEvent (enterFrame) {      if (butterfly hasn't reached the target yet) {           move butterfly one increment to the right;           move b'fly vertically  amount depends on sine of x;      } } 

The sine function goes through one full cycle (from peak to peak) as the x argument goes from 0 to 360 (traditionally visualized as the degrees of a circle). This example makes the butterfly go through one full sine wave by varying _x from 0 to 360.

Sample movie sine.fla expresses this logic in ActionScript. It has to make two adjustments: It adds a "y adjustment" variable ( yadj ), which increases the amplitude of the sine wave. Without this adjustment, the movement of the butterfly up and down would be very slight . It also uses the deg2rad() function to convert the degree measurement to radians. Here's the code:

 // converts degrees to radians function deg2rad (degrees) {      return degrees * Math.PI/180; } bfly.startx = 0; // x starting point bfly.endx = 360; // x ending point bfly.starty = 112; bfly._x = startx; // position the bfly at start bfly._y = starty; // position the bfly at start bfly.xinc = 16; // x increment for movement to the right in each frame bfly.yadj = 8; // y adjustment  increases amplitude of sine wave } bfly.onEnterFrame = function() {      if (bfly._x < bfly.endx) {           bfly._x += bfly.xinc; // move bfly one increment to the right           // move bfly vertically, amount depends on sine of x           bfly._y += bfly.yadj * Math.sin(deg2rad(bfly._x));      } } 

Controlling Speed with Math.sin()

You can apply the sine function to get the clip to speed up and slow down in a smooth, natural-looking way, too. Figure 21.7 shows what happens if, instead of moving the butterfly to the right the same amount in each frame, you vary the increment using the Math.sin() function. Instead of _x += xinc , you use _x += xinc + (xadj * Math.sin(deg2rad(_x))) . This includes an x adjustment variable ( xadj ), set to 8 here, which exaggerates the amount of speed-up and slow-down. From 0 “180 °, the sine is positive, so the butterfly speeds up while moving down. From 180 “360 °, the sine is negative, so the butterfly slows down while moving up.

Figure 21.7. Controlling speed using the Math.sin() method. The butterfly slows down as it moves up. (Human figure produced with Poser 4, Curious Labs.)

graphics/21fig07.gif


Remember that, in Flash, "moving down" means _y is getting larger. "Speeding up" means increasing the amount added to _x in each frame. Thus, a positive sine makes the butterfly move downward and speed up. Conversely, a negative sine makes the butterfly move upward and slow down. The changes in speed are indicated by the horizontal distances between the dots.

The slow-down means that the butterfly is in the 180 “360 ° range for more frames than it is in the 0 “180 ° range. (In Figure 21.7, each dot is one frame. Notice how many more dots there are in the second half of the butterfly's journey.) Thus, _y += yadj * Math.sin(deg2rad(_x)) is executed more times with a negative sine than with a positive sine, making the butterfly move up farther than it moves down. Compensate for this by starting lower, substituting var starty = 175 for var starty = 112 . (See sample movie sine2.fla on the CD.)

Other Trig Methods

Here are the other trig methods, specified in terms of the sine and cosine of a unit circle. Substitute y/r for sin and x/r for cos if r does not equal 1 . The angle theta is specified in radians in all cases.

The arcsin ( asin ) method returns the angle given the sine:

 theta = asin(sin) theta = Math.asin(y/r); 

The arccos ( acos ) method returns the angle given the cosine:

 theta = acos(cos) theta = Math.acos(x/r); 

The tangent ( tan ) method returns the sine divided by the cosine:

 sin/cos = tan(theta) y / x = Math.tan(theta); 

The arctangent ( atan ) method returns the angle given the tangent:

 theta = atan(sin/cos) theta = Math.atan(y/x) ; 

The System Object

graphics/new_icon.jpg

The System object (which is a singleton, like the Math object) represents the computer (or other device, such as a PDA) on which the Flash Player is running. In Flash MX, the System object had only one property, capabilities , with 10 documented properties. In Flash MX 2004, the capabilities object has 26 properties, listed in Table 21.10.


Table 21.10. System.capabilities Properties

Properties

Meaning

Example

Comment

avHardwareDisable

Gets enabled/disabled status of camera and microphone

true

true means disabled ( [n] )

hasAccessibility

Supports accessibility features

false

 

hasAudio

Has audio capabilities

true

 

hasAudioEncoder

Has an audio encoder

true

 

hasEmbeddedVideo

System supports embedded video

true

( [n] )

hasMP3

Can play MP3 files

true

 

hasPrinting

Has printing capability

true

( [n] )

hasScreenBroadcast

Supports development of screen broadcast applications (through Flash Communication Server)

false

( [n] )

hasScreenPlayback

Can play back screen broadcast applications (through Flash Communication Server)

false

 

hasStreamingAudio

Can play streaming audio

true

( [n] )

hasStreamingVideo

Can play streaming video

true

( [n] )

hasVideoEncoder

Has a video encoder

true

 

isDebugger

Debugger is active (special debugging version of Flash Player)

true

( [*] )

language

Gets the language, two character code defined in ISO 639-1

en

( [*] )English

localFileReadDisable

Disabled/enabled status for local file reading

true

true means disabled ( [n] )

manufacturer

Gets the manufacturer's string

Macromedia Windows

( [*] )

os

Gets the operating system

Windows 2000

( [*] )

pixelAspectRatio

Gets the pixel aspect ratio

1

 

playerType

Gets type of Flash Player

"StandAlone", "External", "PlugIn", "ActiveX"

( [n] )

screenColor

Gets color, black & white (bw), or grayscale (gray) screen type

color

 

screenDPI

Gets screen dots per inch in pixels

72

 

screenResolutionX

Gets horizontal screen resolution (pixels)

1024

 

screenResolutionY

Gets vertical screen resolution (pixels)

768

 

serverString

Gets the string to send to server

A=t&MP3=t&AE=t& VE=t&ACC=f&DEB=t& V=WIN%206 %2C0%2C21 %2C0& M=Macromedia Windows& R=1024x768 &DP=72& COL=color&AR=1.0& I=point&OS= Windows 2000& L=en-US

( [*] )

version

Gets the version of Flash Player

WIN 7,0,0,231

( [*] )

windowlessDisable

Enabled/disabled status of browser's windowless modes

true

true means disabled ( [n] )


[n] in Comment column indicates new feature, not present in Flash MX.

[*] in Comment column indicates feature was present but undocumented in Flash MX.

All the System.capabilities properties are effectively read-only. Although you may be able to set (change) them, it doesn't accomplish anything.

The serverString summarizes all the system capabilities in a single string that can be sent to a communications or application server. Note that serverString has been broken up into multiple lines so that it fits into Table 21.10. In practice, you receive it as a single, unbroken string, and that is how it is sent to the server, as well.

In addition, new features in Flash Player 7 include an onStatus event, two methods ( setClipboard and showSettings ), two Boolean attributes ( useCodepage and exactSettings ), and the security object, which has two methods ( allowDomain and allowInsecureDomain ).

The onStatus event is a "catch-all" event that can trap onStatus events for LocalConnection , NetStream , or SharedObject objects. Any time you don't create an onStatus event for any of these objects, the event will be trapped by the System.onStatus event handler, assuming you have created one.

SharedObject and LocalConnection are covered later in this chapter under "The Shared Object Class," page 602 , and "The LocalConnection Class," page 596 . For more on the NetStream class, see " NetConnection , NetStream and the Rich Media Classes," page 647 , in Chapter 22, "External Communications."


The setClipboard method allows you to write text to the system clipboard.

The showSettings method shows the settings in the Flash Player settings panel.

The useCodepage attribute tells the Flash Player whether external text files will be encoded using the default single-byte character codes associated with the Windows or Mac operating system (the default, true ), or whether they will use double-byte Unicode ( false ).

For more on Unicode, see unicode.htm on the CD accompanying this book.


The rest of the features all pertain to security.

The exactSettings attribute determines whether several URLs in the same main domain (for example, http://myHost.ourDomain.com and http://yourHost.ourDomain.com ) access local settings (such as camera or microphone access permissions) or locally persistent data (shared objects) from a single source ( http://ourDomain.com ), or whether each URL does so from its own individual local source. The default is true for SWFs published for Flash Player 7 (requiring the local settings to be stored separately for each subdomain), and false for SWFs published for Flash Player 6 (allowing shared storage for the local settings).

The allowDomain method specifies which domains are allowed to access objects and variables in movies in the same domain as the movie executing the allowDomain method (which includes the movie executing the method itself). In Flash Player 6, you can just specify the main domain name, like this:

 System.security.allowDomain("yourDomain.com"); 

In Flash Player 7, you need to specify full domain names:

 System.security.allowDomain("www.yourDomain.com", "yourHost.yourDomain.com"); 

In movies published for Flash Player 6, allowDomain allows a container SWF loaded via HTTPS (HTTP Secure) to be accessed by SWFs loaded via non-secure HTTP. This is a lax behavior, which was eliminated for movies published for Flash Player 7, where objects and variables in HTTPS-based SWFs can by default be accessed only by other HTTPS-based SWFs. If you want to relax this rule to allow insecure SWFs to access secure SWFs in movies published for Flash Player 7, you must use allowInsecureDomain .



Using Macromedia Studio MX 2004
Special Edition Using Macromedia Studio MX 2004
ISBN: 0789730421
EAN: 2147483647
Year: N/A
Pages: 339

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net