In the last section, we created a function that executed a simple trace( ) statement—not exactly the most compelling specimen of the function species. Here's a more interesting function that moves a movie clip instance, named ball, a short distance. Follow these steps to create it in your own movie:
Create a new empty Flash movie.
Create a new movie clip symbol, named ballSymbol, that contains a circle shape.
Place an instance of ballSymbol on Layer 1.
Name the ballSymbol instance ball.
On frame 1 of Layer 1 of the main movie timeline, attach the following code:
// Store a portable reference to the main timeline. _global.mainTimeline = this; function moveBall () { mainTimeline.ball._x += 10; mainTimeline.ball._y += 10; }
As a matter of good form, functions should not access external timeline variables (such as ball) directly. Therefore, we access ball through our application's global reference to the movie's main timeline. With the function moveBall( ) defined, we can move the ball clip diagonally by calling the moveBall( ) function. Add the following code to the existing code on frame 1.
moveBall();
The ball moves diagonally down and to the right. (Note that the origin (0, 0) is in the upper left of the main Stage. Increasing values of _x move the ball to the right, but, unlike the Cartesian coordinates, increasing values of _y move the ball down, not up.)
Our moveBall( ) function is convenient, but it lacks flexibility. It works only on one movie clip (ball), it moves ball in only one direction, and it always moves ball the same distance.
A well-designed function should work in many circumstances. We can generalize our moveBall( ) function so that it can move any clip any distance in any direction. The first step in generalizing a function is determining what factors control its behavior. In our moveBall( ) function, the factors are the name of the movie clip to move, the distance to move it horizontally, and the distance to move it vertically. Such factors are known as the parameters of the function—they're the information that we'd like to be able to change each time the function is called.
Recall the generic syntax of a simple function declaration:
function funcName (param1, param2,...paramn) { statements }
A function's parameters are variables that can be used within the function but whose values are determined when the function is executed. We specify parameters as a comma-separated list of legal identifiers between the parentheses of a function declaration, as shown in the previous code fragment.
Once defined, we can access a function's parameter values from inside the function body just as we would any other variable. For example, here is a function with one parameter:
function say (msg) { // Define the msg parameter trace("The message is " + msg); // Use msg within the trace( ) statement }
Our function declaration defines the parameter msg. The trace( ) statement uses the msg parameter as it would any variable, in this case displaying its value to the Output window.
Let's use parameters with our function so that we can set the clip's name, horizontal distance, and vertical distance differently each time it runs. Example 9-1 shows the revised code.
function moveClip (theClip, xDist, yDist) { theClip._x += xDist; theClip._y += yDist; }
We renamed the function from moveBall( ) to the generic name moveClip( ) to reflect its ability to work with any clip. We also defined three parameters: theClip (the movie clip we want to move), xDist (the horizontal distance to move), and yDist (the vertical distance to move). Inside the function body, we use those parameters instead of the literal "hardcoded" values in the earlier moveBall( ) example, thereby allowing our function to reposition any clip by any horizontal and vertical distance. Notice that we no longer need the global variable mainTimeline because the function is told which clip to move when it is invoked. We'll cover invoking moveClip( ) and specifying its parameter values in the next section.
When we create a function, we define the parameter names, which are essentially placeholders for data values. When we invoke the function, we'll provide values to be plugged in for each of the parameters.
The terms parameters and arguments are used interchangeably in common discussion and in most documentation. Technically, arguments are the values used when invoking a function, and parameters are the placeholders in the function that "receive" the arguments.
Recall the generic syntax of function invocation with no arguments:
funcName()
To supply (or pass) arguments to a function, we provide a list of values within the parentheses when invoking the function:
funcName(arg1, arg2, arg3,...argn)
The values used as arguments can be any legitimate expression in ActionScript, including compound expressions. For example, earlier we defined a simple function, say( ), that expects a single parameter, msg:
function say (msg) { trace("The message is " + msg); }
To invoke say( ), we use a statement like this:
say("This is my first argument...how touching");
or like this:
say(99);
or even like this:
now = new Date( ); say(now)
Notice that the values, "This is my first argument . . . how touching", 99, and today's date, belong to different datatypes. ActionScript allows us to pass any data of any type to a function, as long as the function knows what to do with the passed value. (Languages such as C and Java require that we predefine the datatype for each parameter, and they display an error if data of the wrong type is provided.)
Before each argument is passed, its value is fully resolved. Therefore, we can also invoke functions with complex expressions. It is very common to use variables or expressions containing variables as arguments to functions. For example:
var name = "Gula"; say("Welcome to my web site " + name);
Because the expression "Welcome to my web site " + name is evaluated before it is passed to the say( ) function, the function receives the resolved value "Welcome to my web site Gula". This means that we can programmatically generate function arguments—the arguments specified when invoking the function can differ based on things that change at runtime, such as the user's name or the date. This is powerful stuff.
To pass more than one argument to a function, we separate our arguments with commas. Recall that our moveClip( ) function from Example 9-1 accepts three parameters: theClip, xDist, and yDist. Invoking moveClip( ), therefore, looks like this:
moveClip(ball, 5, -15);
Each of the three arguments is assigned as the value of the corresponding parameter named in the function declaration: ball is assigned to theClip, 5 is assigned to xDist, and -15 is assigned to yDist. The correspondence between parameters and arguments is based purely on their order in the comma-separated lists; the first argument specified in the function invocation corresponds to the first parameter in the function declaration, the second argument corresponds to the second parameter, etc. The contents of the arguments used in the function invocation are passed into the function body, where they are referenced by the parameter names used in the function declaration. That is, even though the ball identifier was used as the argument when invoking the moveClip( ) function, the ball movie clip instance is known by the parameter name theClip within the function body.
|
We can move any clip any distance by invoking our generic moveClip( ) function with different arguments. For example, to move a clip instance named square to the right 2 pixels and down 100 pixels, we use:
moveClip(square, 2, 100);
Note that if we want to move the clip horizontally but not vertically, we can simply specify a yDist of 0, such as:
moveClip(square, 2, 0);
Conversely, we can move the clip vertically but not horizontally by specifying an xDist of 0:
moveClip(square, 0, 100);
Therefore, instead of three separate functions, we can use a single function to move the clip horizontally, vertically, or both, by specifying varying arguments in the function invocation. Avoiding unnecessary proliferation of functions keeps our code compact and maintainable.
To pass a value for a single parameter only, even when multiple parameters are expected by a function, use undefined as a placeholder for empty parameter values. For example,
function showName (first, middle, last) { trace("The name is " + first + " " + middle + " " + last); } showName(undefined, undefined, "moock");
Of course, you should use this approach only when the function allows empty arguments to be passed. When building a function that must receive a value for a particular parameter, be sure to test for that value inside the function. For example, here we revise the showName( ) function so that it demands a value for each of its parameters:
function showName (first, middle, last) { // If the parameters are not valid... if (first = = = undefined || middle = = = undefined || last = = = undefined) { // Show an error, then quit. trace("INVALID ARGUMENT VALUES SPECIFIED"); return; } trace("The name is " + first + " " + middle + " " + last); }