You've already seen many of the fundamental elements that make up ActionScript: data, variables, operators, statements, functions, and arguments. Before we delve deeper into those topics, let's sketch out the rest of ActionScript's core features.
To most computer users, a program is synonymous with an application, such as Adobe Photoshop or Macromedia Dreamweaver MX. Obviously, that's not what we're building when we program in Flash. Programmers, on the other hand, define a program as a collection of code (a series of statements), but that's only part of what we're building.
A Flash movie is more than a series of lines of code. Code in Flash is intermingled with Flash movie elements, such as frames, movie clips, graphics, and buttons. In the end, there really isn't such a thing as a Flash "program" in the classic sense of the term. Instead of complete programs written in ActionScript, we have scripts: code segments that give programmatic behavior to our movie, just as JavaScript scripts give programmatic behavior to HTML documents. The real product we're building is not a program but a complete Flash movie (the exported .swf file, including its code, timelines, visuals, sound, and other assets).
Our scripts include most of what you'd see in traditional programs, without the operating system-level stuff you would write in languages like C++ or Java to place graphics on the screen or cue sounds. We're spared the need to manage the nuts and bolts of graphics and sound programming, which allows us to focus most of our effort on designing the behavior of our movies.
The statements of a script, as we've learned, contain the script's instructions. But most instructions are pretty useless without data. When we set a variable, for example, we assign some data as its value. When we use the trace( ) command, we pass data as an argument for display in the Output window. Data is the content we manipulate in our ActionScript code. Throughout your scripts, you'll retrieve, assign, store, and generally sling around a lot of data.
In a program, any phrase of code that yields a single datum when a program runs is referred to as an expression. The number 7 and the string "Welcome to my web site," are both very simple expressions. They represent simple data that will be used as-is when the program runs. As such, these expressions are called literal expressions, or literals for short.
Literals are only one kind of expression. A variable may also be an expression (variables contain data and can stand in wherever data is needed, so they count as expressions). Expressions get even more interesting when they are combined with operators to form larger expressions. For example, the complex expression 4 + 5 includes two operands, 4 and 5, but the plus operator makes the entire expression yield the single value 9. Complex expressions may contain other, shorter expressions, provided that the entire phrase of code can still be converted into a single value.
Here we see the variable message:
var message = "Hi there, Flash!";
If we like, we can combine the variable expression message with the literal expression " How are you?" as follows:
message + " How are you?"
which becomes "Hi there, Flash! How are you?" when the program runs. You'll frequently see complex expressions that include shorter expressions when working with arithmetic, such as:
(2 + 3) * (4 / 2.5) - 1
It's important to be exposed to expressions early in your programming career, because the term "expression" is often used in descriptions of programming concepts. For example, I might write, "To assign a value to a variable, type the name of the variable, then an equals sign followed by any expression."
In nearly all programs, we'll use conditionals to add logic to our programs and loops to perform repetitive tasks.
One of the really rewarding aspects of Flash programming is making your movies smart. Here's what I mean by smart: Suppose a girl named Wendy doesn't like getting her clothes wet. Before Wendy leaves her house every morning, she looks out the window to check the weather, and if it's raining, she brings an umbrella. Wendy's smart. She uses basic logic�the ability to look at a series of options and make a decision about what to do based on the circumstances. We use the same basic logic when creating interactive Flash movies.
Here are a few examples of logic in a Flash movie:
Suppose we have three sections in a movie. When a user goes to each section, we use logic to decide whether to show her the introduction to that section. If she has been to the section before, we skip the introduction. Otherwise, we show the introduction.
Suppose we have a section of a movie that is restricted. To enter the restricted zone, the user must enter a password. If the user enters the right password, we show her the restricted content. Otherwise, we prohibit access.
Suppose we're moving a ball across the screen, and we want it to bounce off a wall. If the ball reaches a certain point, we reverse the ball's direction. Otherwise, we let the ball continue traveling in the direction it was going.
These examples of movie logic require a special type of statement called a conditional. Conditionals let us specify the terms under which a section of code should�or should not�be executed. Here's an example of a conditional statement:
if (userName = = "James Bond") { trace ("Welcome to my web site, 007."); }
The generic structure of a conditional is:
if (this condition is met) { then execute these lines of code }
You'll learn more about the detailed syntax of conditionals in Chapter 7. For now, remember that a conditional allows Flash to make logical decisions.
Not only do we want our movies to make decisions, we want them to do tedious, repetitive tasks for us. That is, until they take over the world and enslave us and grow us in little energy pods as . . . wait . . . forget I told you that . . . ahem. Suppose you want to display a sequence of five numbers in the Output window, and you want the sequence to start at a certain number. If the starting number is 1, you can display the sequence like this:
trace (1); trace (2); trace (3); trace (4); trace (5);
But if you want to start the sequence at 501, you'd have to retype all the numbers as follows:
trace (501); trace (502); trace (503); trace (504); trace (505);
We can avoid that retyping by making our trace( ) statements depend on a variable, like this:
var x = 1; trace (x); x = x + 1; trace (x); x = x + 1; trace (x); x = x + 1; trace (x); x = x + 1; trace (x);
On line 1, we set the value of the variable x to 1. Then at line 2, we display that value in the Output window. On line 3, we say, "Take the current value of x, add 1 to it, and stick the result back into our variable x," so x becomes 2. Then we display the value of x in the Output window again. We repeat this process three more times. By the time we're done, we've displayed a sequence of five numbers in the Output window. The beauty is that if we now want to change the starting number of our sequence to 501, we just change the initial value of x from 1 to 501. Because the rest of our code is based on x, the entire sequence changes when we change the initial value.
That's an improvement over our first approach, and it works pretty well when we're displaying only five numbers, but it becomes impractical if we want to count to 1,000. To perform highly repetitive tasks, we use a loop�a statement that causes a block of code (i.e., one or more instructions) to be performed a specified number of times. There are several types of loops, each with its own syntax. One of the most common loop types is the while loop. Here's what our counting example would look like as a while loop instead of as a series of individual statements:
var x = 1; while (x <= 5) { trace (x); x = x + 1; }
The keyword while indicates that we want to start a loop. The expression (x <= 5) governs how many times the loop should execute (as long as x is less than or equal to 5), and the statements trace(x); and x = x + 1; are executed with each repetition (iteration) of the loop. As it is, our loop saves us only five lines of code, but it could save us hundreds of lines if we were counting to higher numbers. And our loop is flexible. To make our loop count to 1,000, we simply change the expression (x <=5) to (x <=1000):
var x = 1; while (x <= 1000) { trace (x); x = x + 1; }
Like conditionals, loops are one of the most frequently used and important types of statements in programming.
So far, your longest script has consisted of five lines of code. But it won't be long before those five lines become 500, or maybe even 5,000. When you want to manage your code more efficiently, reduce your work, and make your code easier to apply to multiple scenarios, you'll learn to love functions. A function is a packaged series of statements that performs some useful action or calculation. In practice, functions serve mostly as reusable blocks of code.
Suppose you want to write a script that calculates the area of a 4-sided figure. Without functions, your script might look like this:
var height = 10; var width = 15; var area = height * width;
Now suppose you want to calculate the area of five 4-sided figures. Your code quintuples in length:
var height1 = 10; var width1 = 15; var area1 = height1 * width1; var height2 = 11; var width2 = 16; var area2 = height2 * width2; var height3 = 12; var width3 = 17; var area3 = height3 * width3; var height4 = 13; var width4 = 18; var area4 = height4 * width4; var height5 = 20; var width5 = 5; var area5 = height5 * width5;
Because we're repeating the area calculation over and over, we are better off putting it in a function once and executing that function multiple times:
function area(height, width){ return height * width; } area1 = area(10, 15); area2 = area(11, 16); area3 = area(12, 17); area4 = area(13, 18); area5 = area(20, 5);
In this example, we first create the area-calculating function using the function statement, which defines (declares) a function just as var declares a variable. Then we give our function a name, area, just as we give variables names. Between the parentheses, we list the arguments that our function receives every time it's used: height and width. And between the curly braces ({ }), we include the statement we want executed:
return height * width;
After we create a function, we may run the code it contains from anywhere in our movie by using the function's name. In our example we called the area( ) function five times, passing it the height and width values it expects each time: area(10, 15), area(11, 16), and so on. The result of each calculation is returned to us, and we store those results in the variables area1 through area5. This is nice and neat, and much less work than the nonfunction version of our code shown earlier. Enclosing reusable code within functions save us time and reduces the number of lines of code needed. It also makes our code much more legible and modular. Someone reading the code can probably guess what the area( ) function does, based solely on its name.
Don't fret if you have questions about this function example; we'll learn more about functions in Chapter 9. For now, just remember that functions give us an extremely powerful way to create complex systems. Functions help us reuse our code and package its functionality, extending the limits of what is practical to build.
Notice that functions take arguments just as the trace( ) command does. Invoking the function area(4, 5); looks very much the same as issuing the trace( ) command such as trace (x); except that the area( ) function requires two arguments, which are separated by commas, whereas the trace( ) command requires a single argument. The similarity is not a coincidence. As we learned earlier, many Actions, including the trace( ) Action, are actually functions. But they are a special type of function that is built into ActionScript (as opposed to user-defined functions, like our area( ) function). It is, therefore, legitimate�and technically more accurate�to say, "Call the gotoAndStop( ) function," than to say, "Execute a gotoAndStop Action." A built-in function is simply a reusable block of code that comes with ActionScript for our convenience. Built-in functions let us do everything from performing mathematical calculations to controlling movie clips. All the built-in functions are listed in Part II, the ActionScript Language Reference. We'll encounter many of them as we learn ActionScript's fundamentals.
We've learned that a statement is an ActionScript command that makes Flash do something. And we know that a function groups multiple statements into a single convenient command. Functions provide organization for our code that lets us build more complex programs. Objects take the next logical step�they package a series of related functions and variables into a single code module.
As a program's complexity increases, it becomes more and more difficult to describe its operation as a single linear set of instructions (statements). Objects help us conceptually model the behavior of a program as an interrelated series of self-contained components, rather than a long list of commands. For example, in the bouncing ball example from the beginning of this chapter, we could use objects to represent the bouncing ball and the square room in which the ball bounces. The ball object would encompass functions that relate to the ball, such as startMoving( ), stopMoving( ), and checkForWall( ). It would also contain information about the ball, stored in variables such as velocity, color, and diameter. The room object might include the functions setRoomSize( ) and addBall( ) and the variables width and height. When we use objects, our program's conceptual model is reflected by an intuitive syntax that looks like this:
room.addBall( ); ball.diameter = 5; ball.startMoving( );
In general terms, the object (noun) comes first, followed by a dot (.), followed by either a function (verb) or a variable (adjective). The function does something to the object, while the variable tells us something about the object. Functions associated with an object are often called methods. Variables associated with an object are often called properties. Here are some examples:
object.method( ); boy.run( ); someMovieClip.play( ); object.property = value; boy.speed = 5; someMovieClip._width = 60;
Object-oriented programming (OOP) is an approach in which objects are the fundamental building blocks of a program. There are, however, varying degrees of OOP depending on the language and the developer's taste. Purists insist that every part of a program should be contained by an object (this rule is enforced by the Java programming language). Others are happy using objects to structure only certain parts of a program (this is common in ActionScript).
Regardless, you should become familiar with objects, because they are intrinsic to ActionScript's makeup. Nearly everything in Flash�from buttons to text fields to movie clips�is represented in ActionScript by an object. Even if you never organize your own code with objects, you'll have to use object-oriented programming techniques to control the buttons, text, and movie clips in your movie. Chapter 12 covers object-oriented programming in exhaustive detail. For now, just start thinking of things in Flash, such as movie clips, as objects that can perform certain tasks (e.g., play( )) or store information (e.g., _width).
With all this talk about programming fundamentals, I hope you haven't forgotten about the basics of Flash. One of the keys to visual programming in Flash is movie clip instances. As a Flash designer or developer, you should already be familiar with movie clips, but you may not think of movie clips as programming devices.
Every movie clip has a symbol definition that resides in the Library of a Flash movie. We can add many copies, or instances, of a single movie clip symbol to a Flash movie by dragging the clip from the Library onto the Stage. We can also create movie clips at runtime via ActionScript. All visual programming in Flash involves some degree of movie clip instance control. For example, a bouncing ball is nothing more than a movie clip instance that is repositioned on the Stage repetitively. Using ActionScript, we can alter an instance's location, size, current frame, rotation, and so forth, during the playback of our movie.
If you're unfamiliar with movie clips and instances, see "Working with Movie Clips and Buttons" under Help Using Flash before continuing with the rest of this book.
The final topic in our overview of ActionScript fundamentals is the execution model, which dictates when the code in your movie runs (is executed). You may have code attached to various frames, buttons, and movie clips throughout your movie, but when does it all actually run? To answer that question, let's take a short stroll down computing history's memory lane.
In the early days of computing, a program's instructions were executed sequentially, in the order that they appeared, starting with the first line and ending with the last line. The program was meant to perform some action and then stop. That kind of linear program, called a batch program, doesn't handle the interactivity required of an event-based programming environment like Flash.
Event-based programs don't run in a linear fashion. They run continuously (in an event loop), waiting for things (events) to happen and executing code segments in response to those events. In a language designed for use with a visual interactive environment (such as ActionScript or JavaScript), the events are typically user actions such as mouseclicks or keystrokes.
When an event occurs, the interpreter notifies your program of the event. Your program can then react to the event by asking the interpreter to execute an appropriate segment of code. For example, if a user clicks a button in a movie, we could execute some code that displays a different section of the movie (navigation) or submits variables to a database (form submission).
But programs don't react to events unless we create event handlers and/or event listeners that tell the interpreter which function to run when a certain event happens. In Flash MX, we create an event handler using the general form:
someObject.onSomeEvent = someFunction;
|
Events always occur in relation to some object in our program. For example, a button might rotate the movie clip in which it resides using the following event handler:
rotateButton.onRelease = rotate;
In natural language, this tells the interpreter, "When the mouse button is released over the rotateButton object, execute the rotate function." The rotate function might look like this:
function rotate ( ) { this._parent._rotation = 45; }
A function that is executed when an event occurs is known as a callback function. As we'll learn in Chapter 10, within a callback function, the keyword this refers to the object that defined the event handler (in our case, rotateButton). In the case of a button reacting to a mouseclick, this refers to the button that was clicked. Using object-oriented syntax, the movie clip in which the button resides is referred to as this. _parent (the movie clip is the button's _parent because it contains the button). Finally, we set the rotation of the parent movie clip to 45 degrees by assigning 45 to this._parent._rotation:
this._parent._rotation = 45;
This literally translates to, "Set the rotation of this button's parent movie clip to 45 degrees."
Our sample button event handler is commonly written more succinctly as:
rotateButton.onRelease = function ( ) { this._parent._rotation = 45; };
Event-based programs are always running an event loop, ready to react to the next event. Events are crucial to interactivity. Without events, our scripts wouldn't do anything�with one exception: Flash executes any code on a frame when the playhead enters that frame. The implied event is simply the playhead entering the particular frame, which is so intrinsic to Flash that no explicit event handler is required.
Events literally make things happen, which is why they come at the end of your first day of ActionScript language school. You've learned what's involved in writing scripts and that events govern when those scripts will be executed. I'd say you're ready to try your first real conversation.