Thursday, December 13, 2007

Orchestrating Multiple Events

Orchestrating Multiple Events

As you've probably figured out by now, different events can occur simultaneously in your movie. For example, the user can have the mouse button pressed down (triggering a press mouse event) while moving the mouse around the screen (triggering a mouseMove clip event). By writing scripts that work in harmony while multiple events are occurring, you can add powerful interactivity to your projects.

In this exercise, you'll orchestrate several events to simulate a cue ball's being hit with a pool stick. Although there are some quite sophisticated ways of doing this, we take an intermediate approach.

  1. Open OrchestratingEvents1.fla in the Lesson02/Assets folder.

    This project contains a single scene with six layers that are named according to their contents.

    The white cue ball is a movie clip instance named ball_mc. We'll soon be attaching some scripts to this clip. To the right of this instance is a transparent-blue rectangle—an invisible button that will contain some scripts, which when used in tandem with those on the ball_mc movie clip instance will facilitate the interactivity we seek. To the right of this button is a graphic of a pool stick. This is a movie clip instance named stick_mc. The timeline of this movie clip contains two frame labels, Starting and PullBack. At the Starting label, the stick is up against the ball. At the PullBack label, the stick is animated so that it looks like it's being pulled to the right, in anticipation of hitting the ball. Just above the pool stick is a text field instance named powerAmount_txt that displays the power at which the ball is hit, based on how far the stick has been "pulled" to the right.

    We're going to set up our project so that when the user presses, pulls away from, and releases the invisible button, the distance between the point where it was first pressed and where it was released will be calculated. That amount will be used to move the ball to the left. The greater the distance, the farther the ball will move to the left.

    Let's begin the scripting process by first creating and declaring some variables our project will eventually use.

  2. With the Actions panel open, select Frame 1 and add this script:

    var power:Number;

    var hitAmount:Number;

    var trackMouse:Boolean;

    var mouseStart:Number;

    var mouseEnd:Number;


    These lines of script are used to declare the five variables our project will use. All but one will hold numeric values. trackMouse will be used to hold a Boolean value of true or false.

  3. With the Actions panel open, select the invisible button and add this script:

    on (press) {

    ball_mc._x = 360;

    ball_mc._y = 180;

    power = 0;

    powerAmount_txt.text = power;

    hitAmount = 0;

    trackMouse = true;

    mouseStart = _root._xmouse;

    }


    Notice the location of this button. It's placed at the tip of the pool stick, just between the stick and the ball—a logical spot because, as the point of impact, it's also the best place from which to "pull back."

    Most of the actions in this script have an initializing effect in our project and are triggered when the mouse button is first pressed. Since we know that the user may want to hit the ball more than once, the first two actions are necessary in order to move the ball back to its initial horizontal (x) and vertical (y) positions, essentially resetting it for the next hit. The next action sets the value of power to 0. This variable's value—which will be used to determine how hard the ball is hit—will change as the pool stick is pulled back. The value must be reset to 0 at the beginning of each hit. The next action simply displays the current value of the power variable in the powerAmount_txt text field.

    A script placed on the ball_mc movie clip instance will use the value of hitAmount to determine the distance the ball should move. We'll set up that script in a moment.

    The next action in the script sets the value of hitAmount to 0. Because this variable's value will change after the ball is hit, this action is used to reset the value when the button is pressed.

    The next action sets the value of trackMouse to true. All you need to understand at this point is that this variable's value acts like a switch for turning on a script that will be attached to the ball_mc movie clip instance.

    The last action records the current horizontal position of the mouse when the button is pressed and places that value in the variable named mouseStart. Shortly, this value will be used to determine the force (hitAmount) at which the ball is hit.

  4. With the Actions panel open, add this script at the end of the current script:

    on (dragOut) {

    stick_mc.gotoAndPlay ("PullBack");

    }

    When the user moves away from the invisible button (with the mouse button still pressed), this action is executed (the dragOut event occurs), moving the stick_mc movie clip instance to the PullBack frame. Here the stick appears to pull back—a nice visual hint to emulate the action occurring onscreen.

  5. With the Actions panel open, add this script at the end of the current script:

    on (releaseOutside) {

    stick_mc.gotoAndStop ("Starting");

    mouseEnd = _root._xmouse;

    hitAmount = mouseEnd - mouseStart;

    trackMouse = false;

    }

    When the invisible button is pressed, moved away from (with the mouse button still pressed), and released (the releaseOutside event occurs), these actions are executed. Because the act of pressing, dragging, then letting go is similar to what you would employ when using a slingshot, we'll use it here to emulate the pool stick's hitting the ball.

    The first action moves the stick_mc movie clip instance to the frame labeled Starting. The stick appears in its starting position, against the ball. This, along with the ball's being set in motion (which we'll discuss in a moment), gives the appearance of the ball's being hit and then moved.

    The next action records the mouse's horizontal position at the time it's released. We now have the mouse's horizontal position when the invisible button was first pressed (mouseStart) as well as when it was released (mouseEnd). Now let's take a look at how the next action uses these two values.

    The value of hitAmount is determined by subtracting mouseStart from mouseEnd. If mouseStart equals 200 and mouseEnd equals 300, hitAmount is assigned a value of 100. This represents the distance the mouse moved from the time the button was first pressed to the time it was released—in other words, the "force" with which our ball was hit, and how far it will move to the left.

    The last action sets the value of trackMouse to false. All you need to understand here is that this value acts like a switch for turning off a script that will be attached to the ball_mc movie clip instance. Remember that when the button is pressed, this value is set to true, turning the script on. Thus, this script is turned on when the button is pressed, and turned off when it's released outside. (We'll explain the script we're turning on and off shortly.)

    The only thing left to do is attach a couple of scripts to the ball_mc movie clip instance. One will move the ball; the other will use the trackMouse variable we've been discussing.

  6. With the Actions panel open, select the ball_mc movie clip instance and add this script:

    onClipEvent (enterFrame) {

    if (_root.hitAmount > 5) {

    this._x = this._x - 10;

    _root.hitAmount = _root.hitAmount - 2;

    }

    }

    This script uses an enterFrame event handler to execute. It contains an if statement that looks at the value of hitAmount on the root timeline before taking action. (Remember that the value of hitAmount is set by the functionality of our invisible button and is used to determine how hard the ball will be hit.)

    The script states that if the value of hitAmount is more than 5, move the ball_mc movie clip instance (this) to its current x position minus 10 (this moves it left) and deduct 2 from the value of hitAmount. As long as hitAmount is more than 5, these actions will be executed 24 times per second because we've used the enterFrame event. As a result, the ball_mc movie clip instance will move 10 pixels to the left 24 times a second. Because the second action subtracts 2 from the value of hitAmount each time it's executed, the value of this variable will eventually drop below 5, which will cause this script to stop executing. It will begin executing again only when hitAmount is assigned a value greater than 5, which, once again, is the functionality the button provides. This is a perfect example of orchestrating several events to accomplish a single interactive goal.
  7. Add this script at the end of the current one:

    onClipEvent (mouseMove) {

    if (_root.trackMouse == true) {

    _root.power = _root._xmouse -_root.mouseStart;

    _root.powerAmount_txt.text = _root.power;

    }

    }


    This script uses a mouseMove event handler to execute. It also contains an if statement that looks at the value of trackMouse on the root timeline before taking action. Remember that the value of this variable is set to true when the invisible button is pressed but false when it's released. Because this script takes action only if its value is true, alternating the value of this variable—as we do with various mouse events—has the effect of turning the script on and off.

    The script states that if the value of trackMouse is true, set the value of the variable named power to equal the difference between the mouse's current horizontal position minus the value of mouseStart. Remember that mouseStart is the recorded horizontal position of the mouse at the moment the invisible button is pressed. The next action is used to display the value of power in the powerAmount_txt text field. Because these actions are executed whenever the mouse is moved (and trackMouse has a value of true), they provide a real-time display of the power used to hit the ball.

    NOTE

    In the end, the value displayed in the powerAmount_txt text field is the same as that assigned to the variable hitAmount, which determines how far the ball moves when hit.

    The concept you need to grasp here is the idea of turning clip event–based scripts on and off using scripts triggered by mouse events—a capability that gives you a great deal of control in an interactive environment. You'll see many more examples of this technique throughout this book.

  8. Choose Control > Test Movie.

    Press the mouse on the tip of the pool stick and move your mouse to the right. You'll notice the interaction. Release the mouse after pulling a distance and notice how the pool stick hits the ball and the ball moves to the left, based on the amount of power applied. After completing the process, try it again. Each time the ball is hit with a different amount of power, it moves accordingly.

  9. Close the test movie to return to the authoring environment and save your work as OrchestratingEvents2.fla.

    This step completes the exercise.

    Understanding Event Handler Methods

    Although we've discussed a number of events thus far, we've really just scratched the surface of Flash reactions. You already know that scripts react to all kinds of triggers: interaction with the mouse, the timeline's reaching a specific frame, movie clip instances entering a scene. But did you know that by using event handler methods, you can make your scripts execute when sounds finish playing, when the stage is resized, or when the text in a text field changes? You can even use event handler methods to extend the functionality of the events we've already used in this lesson.

    Although event handler methods and standard event handlers are used for the same basic purpose (that is, executing a script when something happens in your movie), you must implement them a bit differently.

    By now, you know how to set up a script to be executed as the result of an event. For example, this script is attached to a movie clip instance named myMovieClip_mc and is executed whenever the mouse button is pressed while the instance is present in the scene:

    onClipEvent(mouseDown) {

    this._rotation = 45;

    }


    This script will rotate the movie clip instance by 45 degrees when the mouse button is pressed.

    Using an event handler method, the following script would be placed on a frame of the timeline to accomplish the same purpose, rotating myMovieClip_mc whenever the mouse button is pressed:

    myMovieClip_mc.onMouseDown = function() {

    this._rotation = 45;

    }


    Instead of using onClipEvent to define the event handler (as shown in the first script), here we use a dot (.) to separate the name of the object (in this case myMovieClip_mc) from the event to which it needs to react. And to reiterate, we've placed this script on a frame rather than attached it to the instance.

    Don't worry about the use of function() in the script. We'll provide an in-depth discussion of functions in Lesson 5, "Using Functions." All you need to know about this use of function() is that it's a necessary part of the syntax for implementing the event handler method.

    NOTE

    To execute a particular function when an event handler method is defined, change the syntax to myMovieClip.onMouseDown = nameOfFunction;.


    The actions in the second line of the script (between the curly braces) define what needs to happen when the event occurs.

    Because this script describes how the myMovieClip_mc instance reacts to the onMouseDown event, that instance must exist in the scene at the time the event handler method is defined. This will attach the defined functionality to the instance. By the same token, event handler methods assigned to objects are removed when the object leaves the scene (or is otherwise removed). If the object appears in the scene again, any event handler methods will need to be defined again.

    At first glance, you may be wondering how event handler methods are much different from regular events, and if there are any advantages of using one over the other. That's what we'll discuss next.

    NOTE

    Event handler methods play a large role in the way custom objects are set up to react to events. For more information, see Lesson 7, "Creating Custom Classes."

    Using Event Handler Methods

    All standard event handlers have equivalent event handler methods (also called callback functions or function callbacks). For example:

    on (press) is buttonName_btn.onPress or movieClipName_mc.onPress



    on (release) is buttonName_btn.onRelease or movieClipName_mc.onRelease



    on (enterFrame) is movieClipName_mc.onEnterFrame


    In addition, these event handler methods exist but have no standard event equivalents:

    Buttons/Movie Clips

    nameOfClipOrButton.onKillFocus

    nameOfClipOrButton.onSetFocus


    Sound Objects

    nameOfSoundObject.onLoad

    nameOfSoundObject.onSoundComplete

    nameOfSoundObject.onID3


    Text Fields

    nameOfTextField.onChanged

    nameOfTextField.onKillFocus

    nameOfTextField.onScroller

    nameOfTextField.onSetFocus


    Stage Objects

    Stage.onLoad


    StyleSheet Objects

    nameOfStyleSheet.onResize


    ContextMenu Objects

    nameOfContextMenu.onSelect


    ContextMenuItem Objects

    nameOfContextMenuItem.onSelect


    LoadVars Objects

    nameOfLoadVarsObject.onLoad


    SharedObject Objects

    nameOfSharedObject.onStatus


    LocalConnection Objects

    nameOfLocalConnection.allowDomain

    nameOfLocalConnection.onStatus


    NetConnection Objects

    nameOfNetConnection.onStatus


    NetStream Objects

    nameOfNetStream.onStatus


    XML Objects

    nameOfXMLObject.onData

    nameOfXMLObject.onLoad


    XMLSocket Objects

    nameOfXMLSocketObject.onClose

    nameOfXMLSocketObject.onConnect

    nameOfXMLSocketObject.onData

    nameOfXMLSocketObject.onXML


    You can use numerous events to trigger a script. Because some of these objects are intangible (for example, Sound, LoadVars, and XML), defining event handler methods on a keyframe of the timeline is the only way to execute a script when an event occurs in relation to that object (in contrast to buttons and movie clip instances, which you can select on the stage and to which you can directly attach scripts).

    NOTE

    We will discuss and use many of these event handler methods throughout this book. For more information, see the ActionScript dictionary.


    By attaching a script to a button or movie clip instance using a regular event handler, you pretty much lock down not only what happens when an event occurs but also the events that actually trigger execution of a script. For example:

    on (press) {

    gotoAndPlay(5);

    }


    If you were to attach this script to a button, the button would react only to the press event, performing a single action when that event occurred. To give you an idea of the power and flexibility of event handler methods, assume there's a button instance on the stage named myButton_btn. By placing the following script on Frame 1 of the main timeline (assuming the button exists at that frame), you define how that button will react to certain events:

    myButton_btn.onPress = function() {

    stopAllSounds();

    }

    myButton_btn.onRelease = function() {

    myMovieClip_mc._xscale = 50;

    }


    When pressed, the button will halt all sounds; when released, it will horizontally scale myMovieClip_mc to 50 percent of its original size.

    However, by moving that timeline to Frame 2—which contains the following script (assuming the button exists at Frame 2)—you would change the button's function completely:

    myButton_btn.onPress = null

    myButton_btn.onRelease = null

    myButton_btn.onRollOver = function() {

    stopAllSounds();

    }

    myButton_btn.onRollOut = function() {

    myMovieClip_mc._xscale = 50;

    }


    By using null, you prevent the button from continuing to react to an onPress or onRelease event—and instead instruct it to react to the two newly defined events.

    TIP

    You can also delete an event handler method using this syntax: delete myButton_btn.onPress.


    By using event handler methods, we can change the button's functionality and the events it reacts to—a powerful capability.

    Event handler methods also come in handy for dynamically created objects. Because the act of dynamically creating an object involves putting an object in your movie that wasn't there when the movie was authored, you can't set up the object to react to an event by selecting it (it hasn't been created yet). This is where event handler methods become really useful. Take a look at this sample script:

    _root.createEmptyMovieClip("newClip_mc", 1);

    _root.newClip_mc.onEnterFrame = function(){

    myVariable++;

    }

    _root.newClip_mc.onMouseMove = function(){

    myCursorClip_mc._x = _root._xmouse;

    myCursorClip_mc._y = _root._ymouse;

    }


    After creating a movie clip instance named newClip_mc, we immediately use event handler methods to define what that instance will do when certain events occur.

    In the next exercise, we place event handler methods on Frame 1 of our movie to define how scene elements react to various events. The idea behind this project is that when the user selects a particular text field (or types text into a field), elements in the scene will react and other elements will be dynamically configured to react to various mouse and clip events.

    NOTE

    Although we have used event handlers attached directly to button and movie clip instances thus far in the book, we will be using event handler methods a lot more extensively from this point on. The reason is twofold. First, they're a lot more flexible and dynamic. And second, they allow us to script various elements from a central location—the timeline—which is a recommended practice by Macromedia due to the fact that scattering scripts throughout your project (placed on various instances) makes the project more difficult to debug and manage.


    1. Open CarParts1.fla in the Lesson02/Assets folder.

      This project contains a single scene with eight layers that are named according to their contents.

      The Background layer contains the main background graphic. The CarClip layer contains the red car at the top-left of the stage—a movie clip instance named car_mc. That movie clip's timeline contains a couple of movie clip instances, wheel1_mc and wheel2_mc, which represent the wheels of the car. The next layer, Text Fields, contains three text fields: text1_txt, text2_txt, and text3_txt. As you will see, the way in which the user interacts with these text fields will dictate how the project functions.

      The next layer, Arrows, contains three small arrow movie clip instances: arrow1_mc, arrow2_mc, and arrow3_mc. These arrows appear below each text field and will be set up to move horizontally along the bottom of the text field as text is entered and removed in a field. The next layer, Wheel, contains the movie clip wheelClip_mc, which will be dynamically scripted to react to the onEnterFrame event only when the text1_txt text field has been selected. The layer above that, Speedometer, contains a movie clip instance named speedClip_mc whose timeline contains a short animation of a needle rotating in a gauge, as well as a revving sound. When the clip is played, these animations make the clip appear to operate like the real thing. This instance will be dynamically scripted to play when the onPress event occurs—but only after the text2_txt text field has been selected. The next layer, Fan, contains a movie clip instance named fanClip_mc, which will be set up to react to the onEnterFrame event only when text3_txt has been selected. Finally, Frame 1 of the Actions layer will contain most of the script for our project.
    2. With the Actions panel open, select Frame 1 and add this script:

      text1_txt.onChanged = function(){

      car_mc._x += 2;

      car_mc.wheel1_mc._rotation += 10;

      car_mc.wheel2_mc._rotation += 10;

      arrow1_mc._x = text1_txt._x + text1_txt.textWidth;

      }


      This script defines what happens when the text in the text1_txt text field is changed (added to or deleted).

      The first action is used to move the car_mc instance two pixels to the right by adding 2 to its current x property. The next two actions rotate the wheel1_mc and wheel2_mc movie clip instances (which are in the car_mc instance) by adding 10 degrees to their current rotation values. This will cause them to appear to spin as the car moves right.

      NOTE

      As shown in an earlier script, using + and = in the script is the same as saying, "Add the value on the right of the equals sign to the current value of what is identified on the left"—which in this case is the rotation value of the wheel1_mc and wheel2_mc movie clip instances.

      The last action moves arrow1_mc horizontally so that it appears just below the last letter in the text1_txt text field. It does this by adding the horizontal location of text1_txt (its _x property) to the width of the text in the field. The sum of this amount will position arrow1_mc appropriately. Every time text is changed (onChanged) in text1_txt, these actions will be triggered.
    3. With the Actions panel open, add this script below the script you just added:

      text1_txt.onSetFocus = function(){

      wheelClip_mc.onEnterFrame = function(){

      this._rotation += 30;

      }

      speedClip_mc.onPress = null;

      fanClip_mc.onEnterFrame = null;

      }


      This script defines what happens when the text1_txt text field has been given focus or clicked. (To "focus" on a field means to make it the active field, into which the user can immediately enter information.)

      When this event handler method is triggered, it does an interesting thing: it configures three other event handler methods. Yes, they are that flexible. First, wheelClip_mc is set to react to the onEnterFrame event so that it will spin by an additional 30 degrees each time the event is triggered (24 times a second). This will cause it to spin as soon as text1_txt is selected. Because we will be adding script in the next couple of steps that will enable speedClip_mc and fanClip_mc to react to onPress and onEnterFrame events, respectively, the next two actions are used to remove that functionality when text1_txt is selected.

      The next additions to the script are just a variation on what has been added so far.

    4. With the Actions panel open, add this script below the script you just added:

      text2_txt.onChanged = function(){

      car_mc._x += 2;

      car_mc.wheel1_mc._rotation += 10;

      car_mc.wheel2_mc._rotation += 10;

      arrow2_mc._x = text2_txt._x + text2_txt.textWidth;

      }


      Syntactically and functionally, this script is the same as the script shown in Step 2—with two exceptions. First, it's executed when the text in the text2_txt text field changes. Also, the last action is used to move arrow2_mc horizontally so that it appears just below the last letter in the text2_txt text field.

    5. With the Actions panel open, add this script just below the script you just added:

      text2_txt.onSetFocus = function(){

      wheelClip_mc.onEnterFrame = null;

      speedClip_mc.onPress = function(){

      this.play();

      }

      fanClip_mc.onEnterFrame = null;

      }


      This script is a variation of the script in Step 3. It dictates what occurs when text2_txt is given focus (selected). You'll notice that the speedClip_mc instance is set up to react to an onPress event. Pressing the speedClip_mc instance after text2_txt has been given focus will cause that instance to play. The other actions prevent the wheelClip_mc and fanClip_mc instances from reacting to the onEnterFrame event that other parts of the script define. As you may have realized, the idea behind this functionality is to enable the instance to the left of a text field to react to an event when the field is given focus, but prevent it from reacting to that event when another field is given focus.

    6. With the Actions panel open, add this script below the script you just added:

      text3_txt.onChanged = function(){

      car_mc._x += 2;

      car_mc.wheel1_mc._rotation += 10;

      car_mc.wheel2_mc._rotation += 10;

      arrow3_mc._x = text3_txt._x + text3_txt.textWidth;

      }

      text3_txt.onSetFocus = function(){

      wheelClip_mc.onEnterFrame = null;

      speedClip_mc.onPress = null;

      fanClip_mc.onEnterFrame = function(){

      this._rotation += 20;

      }

      }
      Once again, this script is a variation of those presented in previous steps. It dictates what occurs when text3_txt is given focus or when text within that field changes.

    7. Choose Control > Test Movie.

      Click the top text field (text1_txt); that text field will be given focus and the wheelClip_mc instance will begin spinning. As you type text into the field, two things will occur: the car_mc movie clip instance will move to the right, with its wheels spinning, and the arrow underneath the field will continue to appear just below the last character in the field. Try clicking the speedClip_mc movie clip: notice that nothing happens. Click text2_txt, and that fact changes: the wheelClip_mc instance will quit spinning, and clicking the speedClip_mc instance will make that instance play. Clicking text3_txt will cause the speedClip_mc instance to become inactive again, but the fanClip_mc instance will begin spinning.
    8. Close the test movie to return to the authoring environment and save your work as CarParts2.fla.

      This step completes the exercise.

      Using Listeners

      Just as a single transmitter broadcasts radio waves to thousands of radio receivers, some events can be "broadcast" to any number of objects so that they respond accordingly. You do this by employing what are known as Listeners—events that can be broadcast to objects that have been "registered" to listen for them (listening objects).

      Suppose you wanted an object (sound, movie clip, text field, array, or custom) to react to a certain event's being triggered in your movie. You would first create an event handler method for that object:

      myTextField_txt.onMouseDown = function(){

      myTextField_txt.text="";

      }

      Here we've set up a text field named myTextField_txt to react when the mouse button is pressed. The onMouseDown event is not a standard event that a text field can react to, and at this point it still won't. For the text field to react to this event, you must register the text field as a Listener for the event. You can do so by adding this code:

      Mouse.addListener(myTextField);

      Here the text field is registered with the Mouse object because the onMouseDown event is a Listener of that object. Now, whenever the mouse button is pressed, the event handler method we created earlier will execute. You can set up any number of objects for a single Listener event as long as the object has been given an event handler method to deal with the event, and the object has been registered to listen for that event. If you no longer want an object to listen for an event, you can unregister it using this syntax:

      Mouse.removeListener(myTextField);


      Listeners give you a bit more flexibility for scripting how your projects react to various events.

      NOTE

      Not all events can be treated as Listeners. With this in mind, be aware of which events are listed as Listeners in the Actions toolbox. If an event is not listed as a Listener, other objects cannot be set up to listen to it.


      In the next exercise, in honor of the new History panel found in Flash MX 2004, we'll create our own History panel, named Bygones, using Listeners. Our panel will be used to indicate the following information:

    9. When the mouse button has been pressed, and where it was pressed

    10. If a key has been pressed, and which one

    11. If the stage has been resized, and to what new size

    graphics/02inf31.gif

    1. Open Listeners1.fla in the Lesson02/Assets folder.

      This project contains a single scene with four layers that are named according to their contents.

      The Background layer contains all of the nonfunctional interface graphics. The Components layer contains a List component instance named historyList_lb (in which _lb stands for ListBox).

      NOTE

      For more information on components, see Lesson 10, "Scripting UI Components."

      The Buttons layer contains two buttons: one named enable_btn, and the other named disable_btn. Obviously, the enable_btn button will be used to activate the Bygones panel's functionality, while the disable_btn will be used to deactivate it.

      The Actions layer is currently empty but will eventually contain all the scripts for this project.

    2. With the Actions panel open, select Frame 1 of the Actions layer and add this script:

      var historyArray:Array = new Array ();


      This line of script creates an Array object named historyArray. An Array object is simply an object that can hold multiple pieces of data in indexed positions. You can think of it as a mini-database. Look at this example:

      var directions:Array = new Array();


      The script creates a new Array object named directions. We fill this object with data in this manner:

      directions[0] = "North";

      directions[1] = "East";

      directions[2] = "South";

      directions[3] = "West";


      Our directions array now contains four pieces of data. To access data in the array, you use this syntax:

      myTextField_txt.text = directions[2];


      The script will cause "South" (the text in index position 2 of the array) to appear in the text field.

      In the case of this project, we will be using the historyArray Array object to store information about recorded interactions. For example, a new piece of data will be added to historyArray each time the mouse button is pressed, a key is pressed, or the stage is resized. If the mouse button has been pressed twice and three keys have been pressed, historyArray will contain five items. These five items will each be text descriptions of the particular interaction.

      NOTE

      For more information about arrays and how to use them, see Lesson 6, "Creating and Manipulating Data."

    3. Add this script below the script added in the preceding step:

      historyList_lb.setDataProvider(historyArray);
      The List component we placed in our project is used to provide a mechanism to display the data that will be added to the historyArray Array object. This line of script tells the historyList_lb List component to use the historyArray Array object as its data source. As a result, when we add a new item to the historyArray Array object, it will appear in the historyList_lb List component.
    4. Add this script below the script added in the preceding step:

      historyArray.onMouseDown = function () {

      this.unshift ("Mouse pressed down at x:" + _root._xmouse + " and y:" + _root._ymouse);

      historyList_lb.setSelectedIndex (0);

      };

      This script tells the historyArray Array object what to do when the mouse button is pressed. The onMouseDown event is not one that an Array object can normally respond to, but because this event is also a Listener event of the Mouse object, any object—including our Array object—can be programmed to listen for it when it is triggered. This is only part of the equation that makes this work, however. Eventually, we'll tell the Mouse object to register the historyArray to listen for its events using this syntax:

      Mouse.addListener(historyArray);

      We won't do this yet. We explained it here to help you understand that using Listeners is a two-step process. Let's discuss what this script does.

      The script is triggered when the mouse button is pressed. It adds a new item to our historyArray using this syntax:

      this.unshift(item to add);

      Because this line of our script exists within the overall script that tells historyArray how to react to onMouseDown events, this, in this context, is a relative reference to the historyArray Array object. It could have also been written this way:

      historyArray.unshift(item to add);

      unshift() is a method that an Array object can use to place a new item in the first position of its index, while moving (shifting) all existing items up one position. The data you want to add is placed within the parentheses. According to the directions Array object we discussed earlier, this syntax:

      directions.unshift("North");

      would place the value "North" in index 0 of the directions Array object:

      directions[0]; //has a value of "North"

      Using the unshift() method again:

      directions.unshift("East");

      places the value "East" in index position 0, while moving the value "North" up to index position 1:

      directions[0]; //has a value of "East"

      directions[1]; //has a value of "North"

      In our script, then, every time the mouse button is pressed, the unshift() method is executed and adds the information in the parentheses (which we'll discuss in a moment) to index 0 of historyArray, while moving existing items in the array up one index position. As a result, what appears in the historyList_lb List component will be updated as well.

      Let's look at the information that gets added to the array each time the mouse button is pressed and the unshift() method is executed. Our script shows that what is added looks like this:

      "Mouse pressed down at x:" + _root._xmouse + " and y:" + _root._ymouse

      This represents the structure of the information that will be added to our panel each time the mouse button is pressed. In this case, the x and y positions of the mouse (_root._xmouse and _root._ymouse, respectively) are captured and inserted into the message. When the mouse is pressed down, if it has an x position of 350 and a y position of 100, the message that gets inserted into the historyArray Array object reads as follows:

      "Mouse pressed down at x:350 and y:100"

      Once this gets added to historyArray, this information will also appear in our List component, as a result of earlier scripting of our historyArray (Step 3) to feed data to the List component. Pretty simple, don't you think?

      In the script we added in this step, the last line before the final curly brace reads:

      historyList_lb.setSelectedIndex (0);

      This will cause the top item in the historyList_lb List component to be highlighted. This is simply for cosmetic purposes, so that the last piece of data added to the list will always stand out.

      Next, we script historyArray to listen for when the user presses a key on the keyboard. Fortunately, this script is similar to the one we just discussed.
    5. Add this line of script below the one added in the preceding step:

      historyArray.onKeyDown = function () {

      this.unshift ("Key pressed with ascii value of: " + Key.getAscii ());

      historyList_lb.setSelectedIndex (0);

      };

      This part of our script tells historyArray what to do when a key on the keyboard is pressed. The onKeyDown event specified here is not one that Array objects can normally respond to. But because it is an available Listener event of the Key object, we can use it to program our Array object to do something when a key is pressed.

      This script also uses the unshift() method described in the preceding step. As you can see, this again refers to the historyArray Array object. Thus, whether the mouse button or a key on the keyboard is pressed, the message generated by our script is placed into index 0 of our single Array object (while moving all existing index items up one index number). As a result, our List component will display all messages generated from mouse clicks and key presses.

      The message created when a key is pressed is built around this syntax:

      "Key pressed with ascii value of: " + Key.getAscii ()

      This part of the script uses the Key.getAscii() method to determine the ASCII code for the currently pressed key on the keyboard.

      As a result, if the Spacebar is pressed, it generates a message that looks like this:

      Key pressed with ascii value of: 32

      NOTE

      For a complete list of ASCII values, consult the ActionScript dictionary that comes with Flash.

      As described in Step 4, historyList_lb.setSelectedIndex (0); will highlight the first item in the historyList_lb List component. This action causes all the recently added items to always appear highlighted.

      Finally, let's script historyArray to listen for when the stage is resized.

    6. Add this line of script below the one added in the preceding step:

      historyArray.onResize = function () {

      this.unshift ("Stage resized to W:" + Stage.width + " x H:" + Stage.height);

      historyList_lb.setSelectedIndex (0);


      };

      This script is similar to the last two. It scripts historyArray to react to the resizing of the stage (using the onResize event, which is a Listener event of the Stage object). The message generated by this script will also be added to historyArray. If the stage is resized to a width of 550 and a height of 400, this message will read:

      Stage resized to W:550 x H:400
      It's time to register historyArray with the Mouse, Key, and Stage objects so that it can begin reacting to the events those objects generate. Before we do, however, let's do a test, just so you understand the importance of this registration process.
    7. Choose Control > Test Movie.

      When the movie appears, you can press the mouse button, type keys, and resize the stage to your heart's content, but nothing happens. Simply scripting the historyArray Array object to react to these events doesn't mean it will react. Not yet, at least. Let's go back to the authoring environment and finish the job.
    8. Close the test window to return to the authoring environment. Open the Actions panel and add this script at the end of the current script:

      enable_btn.onRelease = function () {

      Mouse.addListener (historyArray);

      Key.addListener (historyArray);

      Stage.addListener (historyArray);

      };
      This script will execute when the Enable button (named enable_btn) is pressed and released. It registers the historyArray Array object as a Listener of the Mouse, Key, and Stage objects. As a result, the functionality we scripted in the previous steps will come to life when the project is tested again and the Enable button is pressed.

    9. This script will execute when the Disable button (named disable_btn) is pressed and released. It does just the opposite of the script added in the preceding step. Using removeListener(), it unregisters the historyArray Array object as a Listener of the Mouse, Key, and Stage objects. As a result, historyArray will no longer react to Mouse, Key, and Stage events (until the Enable button is pressed again).

      Add this script at the end of the current script:

      disable_btn.onRelease = function () {

      Mouse.removeListener (historyArray);

      Key.removeListener (historyArray);

      Stage.removeListener (historyArray);

      };

      Let's test the project now.
    10. Choose Control > Test Movie.

      When the movie appears, press the Enable button to activate the Bygones panel. Press the mouse button, type on your keyboard, and resize the window the movie is playing in. Each time you perform one of these actions, historyArray will trigger a script as it was set up to do. As a result, you'll see updated information displayed in the List component, representative of the way you are interacting with the movie. Press the Disable button to turn off the functionality of the Bygones panel.

      That's all there is to using Listeners.

      As a side note, be aware that the Mouse, Key, and Stage objects can generate a total of seven Listener events. While the registering process (shown in Step 8) registers historyArray to listen for all of these objects, it is scripted to react to only three of them. For example, the following line in our script:

      Mouse.addListener(historyArray);
      registers historyArray to listen to all four Mouse Listener events, but it is only scripted to react to the onMouseDown event. For historyArray to react to the other three Listener events, you would need additional scripts (as described in Steps 4 through 6).

    11. Close the test movie to return to the authoring environment and save your work as Listeners2.fla.

      This completes the exercise and the lesson.

Event Handlers

Using Event Handlers

We push buttons, we push people, we even push people's buttons, all with a single purpose: to elicit a response. The Macromedia Flash way of saying this is that for every event there is an action.

In a Flash environment, the responses that come from pushing, holding, moving, entering, and leaving are triggered by event handlers. Event handlers represent the first step in getting your movie to do anything interactive—which is why a thorough understanding of them is vital.

We'll create several projects in this lesson, including this self-running presentation that uses frame events to provide the user with a hands-free experience.

graphics/02inf01.gif

WHAT YOU WILL LEARN

In this lesson, you will:

  • Learn how event handlers are used in scripts

  • Determine the best event handler for the job

  • Use mouse/button/keyboard events to control interactivity

  • Create a self-running presentation using frame events

  • Use clip events to create an interactive project

  • Orchestrate multiple events to accomplish a task

  • Define and use event handler methods

  • Learn about Listeners and how to use them

APPROXIMATE TIME

This lesson takes approximately two hours to complete.

LESSON FILES

Starting Files:

Lesson02/Assets/MouseEvents1.fla

Lesson02/Assets/FrameEvents1.fla

Lesson02/Assets/ClipEvents1.fla

Lesson02/Assets/OrchestratingEvents1.fla

Lesson02/Assets/CarParts1.fla

Lesson02/Assets/Listeners1.fla

Completed Projects:

MouseEvents2.fla

FrameEvents2.fla

ClipEvents2.fla

OrchestratingEvents2.fla

CarParts2.fla

Listeners2.fla

What Event Handlers Do

Many computer programs allow users to accomplish tasks by dragging and dropping items on the screen, resizing windows, making adjustments with sliders, and creating artistic masterpieces using "virtual" art tools—all modes of interaction determined by the way in which the software has been programmed to deal with various events (mouse presses, mouse movements, keyboard input, and so on).

Event handlers orchestrate your movies' interactivity by controlling when scripts are triggered. They provide a "when" to a script so that it executes only when something specific occurs. Every script in your movie is triggered by an event—a user rolling over a button or pressing a key, your movie's timeline reaching a certain frame, and so on.

In ActionScript, event handlers (with the exception of frame events) usually represent the first lines in a script. For example:

When this happens (event) {

do this;

do this;

}


Frame events occur when the timeline reaches a frame that contains a script. When you place a script on a frame, you don't need to identify a frame event to trigger that script because the timeline reaching the frame is enough to cause it to execute. If the script were placed in a frame, it would look like this:

do this;

do this;


The better you understand event handlers, the more control you'll have over the user's experience. By using event handlers properly, you can create immersive environments the user will enjoy.

Choosing the Right Event Handler

Using event handlers properly presents one of the biggest challenges for ActionScript users—perhaps because most of us haven't given much thought to how things happen around us, and how to apply what we know when we create interactive environments. However, being mindful of how things and people interact in the real world can go a long way toward helping you re-create such interactions in your Flash movies.

As we introduce you to Flash's many event handlers, we'll examine some of the ways in which their use can be translated into real-world events. As you review these events, remember what you learned at the beginning of this lesson: in Flash, for every event, there is an action (or reaction).

Using Mouse Events

Mouse events control the execution of scripts when the mouse interacts with a button or movie clip instance. You use them to emulate things you might do with your hands.

Making Contact: on (press)

In the physical world, when you touch or press something—a person or an ice cube—you expect a reaction: the person responds, the ice cube melts. The on (press) event handler works great for emulating touching, grabbing, or just plain pushing, as well as the results of any of these actions. You can use this event handler to trigger a script when the cursor is above a button or movie clip instance and the mouse button is pressed.

graphics/02inf02.gif

Letting Go: on (release)

When you release something or cease to make contact with it, you're usually finished interacting with it and ready to move on. This event handler—which emulates letting go of something (or dropping it)—is the most direct way of allowing the user to make your movie take action. It's often used on buttons or movie clip instances to trigger actions. You use it to trigger a script when the mouse button is released (it was first pressed while it was over a button or movie clip instance).

graphics/02inf03.gif

Pulling, Snapping: on (releaseOutside)

Imagine a deck of cards sitting on a table: you push down on the top card with your finger, drag it away from the deck, and then let your finger up. In Flash, this deck of cards could represent a button that the user presses, drags away from, then releases. You can use this event handler to trigger a script when your user has pressed a movie button or movie clip instance but released the mouse away from it, making this event handler useful for emulating pulling or snapping.

graphics/02inf04.gif

Keyboard Control: on (keyPress)

You use this event to program your movie to trigger a script when a user presses a letter, number, punctuation mark, symbol, or arrow key; or the Backspace, Insert, Home, End, Page Up, or Page Down key.

Over But Not Touching: on (rollOver)

You can place your hand over a hot stove and feel the heat without actually touching the stove. Consider using this event handler to emulate the way objects are affected by other objects that radiate heat, cold, light, air, and so on—with the button or movie clip instance as the radiation source. You can also use this event handler to display information about what a button or movie clip instance does before it's pressed (similar to a ToolTip or an HTML hotspot graphic). You employ this event handler to trigger a script when the user places his or her mouse over a button or movie clip instance.

graphics/02inf05.gif

No Longer On Top Of: on (rollOut)

Obviously, when you move your hand away from that stove, you cease to feel the heat it's radiating and your hand cools down. That's what this event handler emulates. You can use this event handler to trigger a script when the user moves the mouse away from a button or movie clip instance it was formerly over.

graphics/02inf06.gif

Grooves, Bumps, Rubbing: on (dragOver)

The act of rubbing entails a back-and-forth motion across an area. When a shoe is being shined (cloth dragged over it), for example, it gets slicker with each pass (action). This event handler lets you emulate this type of activity in your movie by triggering a script each time the mouse passes over the same movie button or movie clip instance while the mouse button remains pressed.

graphics/02inf07.gif

Oops: on (dragOut)

This event handler allows you to emulate what can happen when you press or touch something but then pull away—as if you were to touch someone by accident and quickly pull your hand away once you realize your mistake. You can use this event handler to trigger a script when the user places the pointer over a movie button or movie clip instance, presses the mouse button, and drags it away from the movie button or movie clip instance (while still pressing the mouse button).

graphics/02inf08.gif

In this exercise, we'll create a fingerprint scanner that interacts with the user in various ways. In the process, you'll learn several creative uses for these event handlers, enabling you to emulate rubbing, snapping, and more.

  1. Open MouseEvents1.fla in the Lesson02/Assets folder. Open the Scene panel and Property Inspector.

    We're focusing on the ActionScript that makes this project work, so most of the elements are already in place. Let's get acquainted with what's on the stage.

    The Scene panel shows that our project contains two scenes, Scan and Playroom. We'll begin our work in the Scan scene, which contains five layers that are named according to their content.

    If you select the box in the bottom center of the screen, you'll see in the Property Inspector that this is a dynamic text field with an instance name of message_mc.

    If you select the hand graphic, you'll notice in the Property Inspector that this is a movie clip instance named hand_mc. The black box in the middle of the screen is also a movie clip instance; this one is named scanner_mc. On top of this movie clip instance is a button that appears to be a square piece of glass. Soon we'll attach several scripts to this button.

    graphics/02inf09.gif

  2. Lock the Scanner button layer and double-click the scanner movie clip instance in the middle of the stage to edit it in place.

    You are now looking at this movie clip's timeline. The overall functionality of this movie clip is not important (move the playhead to see how it appears visually at various points). It is, however, important to be aware of the six frame labels on its timeline. One of the functions of the several scripts we'll attach to our Glass button (on the main timeline) will be to move this movie clip's timeline to these various labels whenever a particular mouse event occurs.

  3. Return to the main timeline. With the Actions panel open, select Frame 1 of the Actions layer and add the script:



    stop ();

    Mouse.hide();

    startDrag ("hand_mc", true);

    message_txt.text = "Please place your finger on the scanner and press down. Release after

    graphics/ccc.gif 2 seconds.";


    The first action prevents the movie from moving past this scene until we instruct it to do so. The second action hides the mouse cursor because we will be using the hand_mc movie clip instance as a custom cursor. The third action instructs Flash to drag this instance and move it around the screen as if the instance were the normal mouse cursor. The true parameter in this action automatically centers the dragged clip's center on the tip of the mouse cursor. The last action places the initial text in the text field named message_txt.

    Because these actions are on Frame 1 of the first scene, they occur as soon as the movie begins to play.

  4. With the Actions panel still open, unlock the Scanner button layer, select the button on that layer (which appears as a square sheet of glass), and add the script:

    on (rollOver) {

    scanner_mc.gotoAndPlay ("Active");

    message_txt.text = "Please press on the screen to continue.";

    }


    graphics/02inf10.gif

    When the hand moves over the Glass button, we want to give the impression that it's being "sensed" by the scanner. The rollOver event lets us do that by triggering an action when the hand first hovers over the button. This event handler triggers two actions: it sends the scanner_mc movie clip instance to the Active frame, where a short animation provides a visual cue that the scanner is active and ready to be pressed. It then changes the text being displayed in the message_txt text field.

  5. Add this script just below the current script:



    on (rollOut) {

    scanner_mc.gotoAndPlay ("Inactive");

    message_txt.text = "Please place your finger on the scanner and press down. Release

    graphics/ccc.gif after 2 seconds.";

    }


    As you can see from this addition, a single button can respond to multiple events.

    This script (and the rollOut event that triggers it) addresses what happens when the mouse moves away from the button without pressing it. In this case, the scanner_mc movie clip instance is sent to the Inactive frame, where a short animation provides a visual cue that the scanner is resetting.

    The next action in this script changes the text displayed in the message_txt text field. This is the same text that appears when the movie is first played, once again giving the impression that the scanner has been reset.

  6. Add this script just below the current script:

    on (press) {

    scanner_mc.gotoAndPlay ("Scan");

    message_txt.text = "Now scanning...";

    }


    When the user presses the button and holds it down, this script is triggered. The first action sends the scanner_mc movie clip instance to the frame labeled Scan, where a short, repeating animation of scan lines moving up and down on a scanner provides a visual cue that a scan is taking place.

    The next action in this script changes the text displayed in the message_txt text field.

  7. Add this script below the current script:



    on (dragOut) {

    scanner_mc.gotoAndPlay ("Error");

    message_txt.text = "An error has occurred. You have removed your finger prior to

    graphics/ccc.gif processing. Please try again.";

    }


    This script, and the dragOut event that triggers it, addresses what happens when the mouse button is pressed while over the button but then is dragged away from it while remaining pressed. The thinking here is that the user pressed the button to start the scanning process but then pulled away, abruptly ending the scan. As a result, the scanner_mc movie clip instance is sent to the frame labeled Error, where a short animation provides a visual cue that there was an error in the scan.

    The next action in this script changes the text displayed in the message_txt text field.

  8. Add this script below the current script:

    on (release) {

    scanner_mc.gotoAndPlay ("Process");

    message_txt.text = "Processing your scan...";

    }


    When the user presses the button and releases it, this script is triggered. The first action sends the scanner_mc movie clip instance to the frame labeled Process, where a short animation indicates that something is being processed and then cleared. At the end of this animation, a frame action instructs the main timeline to go to the Room frame and stop. This frame label is actually on Frame 1 of the Playroom scene, the next scene in our project. This functionality allows an action on the movie clip's timeline to move the main timeline between scenes.

    The next action in this script changes the text displayed in the message_txt text field.

    You've now finished setting up this scene. During playback, with proper user interaction, our project should progress to the Playroom scene. Let's continue our work there.

  9. With the Scene panel open, click the scene named Playroom.

    This scene contains seven layers, named according to their contents.

    graphics/02inf11.gif

    In this scene, we attach mouse events to movie clip instances to facilitate interactivity—and in doing so demonstrate how you can employ mouse events in almost the same fashion on buttons as on movie clip instances. In the upper-left portion of the work area, just above the stage, a small circle represents an empty movie clip instance (no graphical content). We'll attach a couple of mouse events to this instance. In the middle of the square piece of wood is a smaller piece of wood, which is a movie clip instance named bump_mc. We'll place a mouse event on this instance that allows us to emulate sanding this bump away. The card on the right side of the stage is a movie clip instance. We'll script this instance to "snap" into place when it's clicked and dragged.

  10. With the Actions panel open, select Frame 1 of the Actions layer and add this script:

    startDrag ("hand_mc", true);


    This action is the same as the one in the previous scene that enabled the hand_mc movie clip instance to be dragged around the stage. Although the mouse remains hidden when the timeline moves from one scene to another (as our project is set up to do), dragging of objects needs to be reinitiated whenever a scene changes, which is what this step does.

  11. With the Actions panel still open, select the small piece of wood (with an instance name of bump_mc) and add this script:

    on (dragOver) {

    this._alpha = this._alpha - 10;

    }

    If the user presses and holds down the mouse button while moving the cursor back and forth over this instance, its opacity will decrease by 10 percent with each pass (dragOver). After 10 passes, the bump will be invisible, producing the effect of rubbing away the bump.

    The way this script works is simple: with each dragOver event, we set the movie clip instance's alpha property (transparency) to equal its current value minus 10. The term this is a contextual reference to the object to which the script is attached.

    NOTE

    For more information about the term this, as well as other target paths, see Lesson 3, "Understanding Target Paths."

  12. With the Actions panel still open, select the card_mc movie clip instance and add the following script:

    on (releaseOutside) {

    this._x = _root._xmouse;

    this._y = _root._ymouse;

    }
    If the mouse is placed on top of the instance, pressed, moved away from the instance (while remaining pressed down), and then released, this script will be executed. The script will move the card_mc movie clip instance's x and y positions to match the x and y positions at the time the event occurs. In other words, suppose the card_mc movie clip instance is on the left side of the stage. If the user places the mouse over the instance, presses and holds down the mouse button, drags the cursor away from the instance (to the right side of the stage, for example), and releases the mouse button, the card_mc instance's position will snap to the right side of the stage—the cursor's location on release of the mouse button.
  13. With the Actions panel open, select the empty movie clip instance (above the stage) and add this script:

    on (keyPress "") {

    _root.bump_mc._alpha = 100;

    }

    on (keyPress "") {

    _root.gotoAndStop (1);

    }

    Here we've added two keyPress events to this movie clip instance. Note that you don't need to place the instance on a visible portion of the stage because the actions attached to it are triggered by keyboard presses rather than cursor interaction.

    The first keyPress event is triggered when the user presses the Spacebar. When this occurs, the transparency of the bump_mc movie clip instance is reset to 100, making it fully visible again (in case it had been rubbed away).

    The second keyPress event is triggered when the user presses the Left Arrow key. When this occurs, the main timeline (_root) is sent back to Frame 1, which contains the Scan scene where the user must scan his or her fingerprint again to return to the Playroom.

    This completes the scripting for our project.

  14. From the menu, choose Control > Test Movie to see the movie in action.

    Interact with the scanner and elements in the Playroom to solidify your understanding of how these events work.
  15. Close the test movie to return to the authoring environment. Save your project as MouseEvents2.fla.

    This completes the exercise. You should now have a thorough understanding of mouse events and the ways you can use them to enhance your projects.

    Using Frame Events

    Frame events are probably the easiest events to understand. When you attach a series of actions to a keyframe on the timeline, Flash executes those actions when the movie reaches that frame during playback. Frame events are great for triggering actions based on the passage of time or actions that need to be synchronized with elements currently visible on the stage.

    NOTE

    Many projects need to have a number of things set in place as soon as they begin to play. Known as initializing, this process usually involves creating data or establishing certain aspects of the movie's functionality. For this reason, many developers place a number of actions on Frame 1 of the main timeline to implement this initialization process. These actions are used to create variables and arrays as well as to define functions—all of which may be needed soon after the movie begins to play.

    In the next exercise, we'll create a simple self-running presentation that displays pictures and related text sequentially, using frame events.

    1. Open FrameEvents1.fla in the Lesson02/Assets folder. Open the Property Inspector.

      First, let's get acquainted with what's on the stage.

      This 200-frame scene contains six layers (named according to their content), five text fields, three buttons, and two movie clip instances. The movie will begin playing at Frame 1, displaying a picture and associated text on the screen. We will place actions on Frame 200 to advance the picture, and send this timeline back to Frame 1 to repeat the process. Because our movie is set to play at 20 frames per second, each picture (and the information it contains) will be visible for 10 seconds (200 frames divided by 20 frames a second) before moving on. If you select the center picture in the left portion of the stage, the Property Inspector indicates that this is a movie clip instance named pictures_mc that itself contains several pictures: these pictures form the basis of our slide show. Soon, we'll add frame events to this clip's timeline. The other movie clip instance, indicator_mc, appears as a small white circle in the lower-right corner of the stage. This instance contains a short animation that alerts the user that the picture is about to change in case he or she wants to pause the presentation.

      The three text fields to the right of the pictures_mc movie clip instances have instance names of (in clockwise order) date_txt, country_txt, and caption_txt. Using frame events, these fields will be filled with information related to the currently displayed picture. Two other text fields appear above and to the left of our control buttons (Play, Stop, and Rewind). The text field above these buttons is named warning_txt because this is where text will be displayed indicating that the picture is about to change. To the left of the control buttons is a text field named balloon_txt. When the user rolls over one of the control buttons, the function of that button will be shown here.
    2. Double-click the pictures_mc movie clip instance in the middle of the stage to edit it in place.

      You're now looking at this movie clip's timeline. It contains two layers labeled Pix and Actions. The Pix layer contains five keyframes, each of which contains a different picture (move the playhead to view these pictures). The Actions layer contains six blank (empty) keyframes. We'll explain shortly why this layer has one more keyframe than the Pix layer.

      Now let's fill these empty keyframes with scripts.

    3. With the Actions panel open, select Frame 1 on the Actions layer and add the script:

      stop ();

      _root.date_txt.text = "June 15th";

      _root.country_txt.text = "Scotland";

      _root.caption_txt.text = " Isn't this a beautiful place?";

      The first action will prevent this movie clip from playing beyond Frame 1 until we instruct it to do so.

      The next three actions place text into the appropriate text fields on the main timeline. This textual information relates to the graphic that appears on Frame 1 of the Pix layer on this timeline. In other words, whenever this timeline is on this frame, the visible picture and the text displayed in the text fields will coincide with one another.
    4. With the Actions panel open, select Frame 2 on the Actions layer and add the script:

      _root.date_txt.text = "June 16th";

      _root.country_txt.text = "Italy";

      _root.caption_txt.text = "The food was excellent!"
      When this movie's timeline is moved to Frame 2, these three actions will update the respective text in the appropriate text fields on the main timeline. This textual information relates to the graphic that appears on Frame 2 of the Pix layer on this timeline.
    5. With the Actions panel open, select Frames 3, 4, and 5 on the Actions layer and add these scripts:

      Place on Frame 3:

      _root.date_txt.text = "June 17th";

      _root.country_txt.text = "Greece";

      _root.caption_txt.text = "We went for a boat ride."

      Place on Frame 4:

      _root.date_txt.text = "June 18th";

      _root.country_txt.text = "France";

      _root.caption_txt.text = "We took another boat ride."

      Place on Frame 5:

      _root.date_txt.text = "June 19th";

      _root.country_txt.text = "Monaco";

      _root.caption_txt.text = "The mountains were amazing!";
      Each of these sets of actions has the same effect as the previous two sets; the only difference is that these are triggered when this movie's timeline is moved to Frames 3, 4, and 5, respectively.
    6. With the Actions panel open, select Frame 6 on the Actions layer and add the script:

      gotoAndStop (1)

      We advance through the frames in this movie clip dynamically by telling Flash to go to the next frame in the timeline—we won't use frame numbers or labels. We run out of pictures after Frame 5, and this script is triggered when the movie clip is advanced to the next frame (Frame 6), immediately sending the timeline back to Frame 1 and the first picture. Our demonstration loops through these five graphics until the presentation is stopped or the user exits it.

      It should be easy to add more pictures and text to the presentation. Let's set up the functionality that advances our presentation through these graphics.
    7. Return to the main timeline. With the Actions panel open, select the keyframe on Frame 140 and add this script:

      warning_txt.text = "The picture will change in 3 seconds.";

      indicator_mc.gotoAndPlay ("On")

      Eventually, Frame 200 will contain a script to advance the picture being displayed. Our movie is set to play at 20 frames per second, so placing this script on Frame 140 will cause it to be executed three seconds (200 frames minus 140 frames equals 60 frames, or 3 seconds) prior to the picture change.

      The first action displays a warning message in the warning_txt text field instance indicating that the picture will change in three seconds. The next action sends the indicator_mc movie clip instance to the frame labeled On, where a short animation acts as a visual cue that the picture is about to change.
    8. With the Actions panel open, select the keyframe on Frame 160 and add this script:

      warning_txt.text = "The picture will change in 2 seconds.";
      This action updates the message in the warning_txt text field to indicate that the picture will be changing in two seconds.

    9. With the Actions panel open, select the keyframe on Frame 180 and add the following script:

      warning_txt.text = "The picture will change in 1 second.";
      This action updates the message in the warning_txt text field to indicate that the picture will be changing in one second.

    10. With the Actions panel open, select the keyframe on Frame 200 and add this script:

      pictures_mc.nextFrame();

      warning_txt.text = "";

      gotoAndPlay (1);

      This set of actions represents the foundation that makes our presentation work. If the act of displaying a picture and its associated text for 10 seconds is a cycle, these actions would be executed at the end of each cycle.

      The first action advances the pictures_mc movie clip instance to the next frame of its timeline. Doing so will cause the next picture to be displayed and the frame actions on that frame to be triggered. This will cause the text info for that picture to be displayed as well.

      The next action clears all text from the warning_txt text field because the warning phase is complete—at least for several seconds.

      The last action sends the main timeline back to Frame 1, which continues to play, and the entire process is repeated.

      We want to let the user control the presentation's playback, so that will be our focus in the next few steps.
    11. With the Actions panel open, select the triangular button on the control panel and add this script:

      on (release) {

      play ();

      }

      on (rollOver) {

      balloon_txt.text = "Play";

      }

      on (rollOut) {

      balloon_txt.text = "";

      }
      This button responds to three events. When the user presses and releases the button, the main timeline plays (though obviously only if the presentation was stopped in the first place). When the user rolls the mouse pointer over the button, the word "Play" will appear in the balloon_txt text field (providing the user with a visual cue about what the button does). When the user rolls the mouse away from the button, the balloon_txt text field is cleared.
    12. With the Actions panel open, select the square button on the control panel and add this script:

      on (release) {

      stop ();

      }

      on (rollOver) {

      balloon_txt.text = "Stop";

      }

      on (rollOut) {

      balloon_txt.text = "";

      }
      This button is also set up to respond to three mouse events. When the user presses and releases the button, the main timeline will stop (though only if it was playing in the first place). When the user rolls the mouse pointer over the button, "Stop" is displayed in the balloon_txt text field (to cue the user about what the button does); and when the user moves the mouse away from the button, the balloon_txt text field is cleared.

    13. With the Actions panel open, select the double-triangle button on the control panel and add this script:

      on (release) {

      gotoAndPlay (1);

      pictures_mc.gotoAndStop (1);

      warning_txt.text = "";

      }

      on (rollOver) {

      balloon_txt.text = "Rewind";

      }

      on (rollOut) {

      balloon_txt.text = "";

      }
      When this button is pressed and released, the main timeline and the pictures_mc movie clip instance are sent back to Frame 1. This action resets the presentation to its original state, regardless of how it has progressed. The next action will display the word "Rewind" in the balloon_txt text field when the user rolls the mouse pointer over the button (to cue the user about what the button does). The rollOut event empties the balloon_txt text field when the user moves the mouse away from the button.

    14. From the menu, choose Control > Test Movie to see the movie in action.

      View the presentation from start to finish to get a feel for how it works. Use the control buttons to control playback.

    15. Close the test movie to return to the authoring environment. Save your work as FrameEvents2.fla.

      You have completed the exercise. Used properly, frame events can aid in creating highly interactive presentations you can add to easily.

    Using Clip Events

    When a movie clip instance with attached scripts enters a scene, that scene can take on a new look, feel, and function through the use of clip events. These events allow actions to be triggered when an instance enters or leaves a scene, when the user moves the mouse around in the scene, and in other ways.

    This section describes the various clip events and provides real-world analogies for their uses. Note that you can use clip events only with scripts attached to movie clip instances.

    Presence: onClipEvent (load)

    When someone or something enters a room or an area, there can be all kinds of ripple effects: the demeanor of people already in the room changes; the environment can be affected in some way; even the person (or thing) entering the room can change as a result of what's going on inside. This event handler provokes a similar response by triggering a script when a movie clip instance enters a scene—useful for initializing the movie clip, for having it be affected by the environment it's entering, or for having it affect the environment.

    Absence: onClipEvent (unLoad)

    If a movie clip instance can affect a scene when it enters, it can also affect the scene when it leaves (sometimes in the opposite way). You can use this event handler to trigger a script when a movie clip instance exits a scene.

    Power, Energy: onClipEvent (enterFrame)

    When an object is given energy or power, it usually signifies that it is taking action on a continuous basis. Consider a clock: without power it sits motionless and useless. If you provide power to it, it ticks, the hands on the face move, and you're able to use it to tell time. This event handler is used to trigger a script continuously, at the same rate as that of your movie as it plays. If your movie's frame rate is set to 20 frames per second, the scripts this event handler triggers are executed 20 times a second. This event handler has many powerful applications, as you'll learn from lessons throughout this book.

    Movement: onClipEvent (mouseMove)

    Think of this event as a motion detector within your movie. If a movie clip instance is present in the scene to which this clip event is attached, a set of actions can be executed each time the user moves the mouse—even if it's just a pixel. This event allows you to create motion-related interactivity—for example, the ability to detect movement direction (right, left, up, and down), current mouse position, and more.

    Computer-Based Interaction: onClipEvent (mouseDown), onClipEvent (mouseUp), onClipEvent (keyDown), onClipEvent (keyUp)

    Because the mouse and keyboard are designed to interact with computers, these clip events don't have real-world equivalents. However, they do provide a means of executing scripts when the user presses (or releases) the mouse button or specific keys. While these events may seem similar to the press, release, and keyPress events described earlier in this lesson, they're a bit more powerful. Using the keyUp and keyDown clip events, you can create key-combinations, or keyboard shortcuts, in your application so that action is taken when a sequence of keys is pressed. In contrast, the keyPress mouse event allows a single key to initiate action. The mouseUp and mouseDown clip events are different from the press and release mouse events because while the latter only trigger scripts when the user interacts directly with a button, the mouseDown and mouseUp events trigger scripts when the mouse is pressed or released anywhere on the stage.

    Receiving Instructions: onClipEvent (data)

    In real life, incomplete instructions can lead to all sorts of problems. The same holds true in Flash. Because Flash lets you load various types of data (variables, external SWFs, JPGs) from external sources into movie clip instances, this event handler plays a vital role because it triggers a script, attached to an instance, only after this data has been completely loaded into it from the source. In doing so, it prevents you from receiving the types of errors that result from incomplete instructions. You can use this event to re-execute actions (refresh) if data is loaded into the clip more than once.

    This is a visual representation of how clip events are triggered. The down arrow represents pressing the mouse button or a key. The up arrow represents releasing the button or key. The asterisk represents an occurrence of the event.

    In the next exercise, we'll create a project that simulates a burglar's getting caught in the act. The burglar's presence (or absence) will determine how the scene plays, and the burglar himself will be programmed to respond to the environment in various ways using clip events.

    1. Open ClipEvents1.fla in the Lesson02/Assets folder. Open the Property Inspector.

      This project contains a single scene that includes seven layers named according to their content. Take special note of the two frames with labels. The one labeled Clear represents the scene without the burglar, and the one labeled Burglar introduces the burglar into the scene. (Move the playhead between these frames to get a handle on this concept because it will be critical to the success of our project.) The burglar graphic is actually a movie clip instance named burglar_mc, which will contain most of the scripts that control our movie's interactivity (more on that in a bit). The burglar_mc movie clip instance is the only movie element that appears and disappears when the user navigates between these two frame labels; all other elements are constantly present. Let's look at these constantly present elements.

      At the top-right of the stage are four buttons. The one that depicts the burglar with the international sign for "No" (red circle with a line through it) on top will eventually be set up to move the scene to the Clear frame, thus "removing" the burglar from the scene. The other three buttons—Tiny, Small, and Normal—will be used to dictate our burglar's size.

      Below these buttons is a light-green circle graphic: a movie clip instance named timer_mc. We will program timer_mc to spin when the burglar is in the scene, giving the sense that it's tracking time.

      Below the timer_mc movie clip instance is a text field named timeAmount_txt. Here, we will be incrementing a number as long as the burglar is present—once again to give the sense that we're tracking time.

      Below this text field are two more text fields, one with an X beside it, the other with a Y. We'll program our burglar to follow the mouse as it moves around. These text fields—mouseXPosition_txt and mouseYPosition_txt, respectively—display the current x and y coordinates of the burglar_mc movie clip instance as it moves.

      Below these text fields is the last text field. Named message_txt, this text field will provide the current status of our environment ("All Clear," "ALERT!" and so on).

      Our scene contains only two other elements—both movie clip instances that need to be examined in depth to be understood.
    2. Double-click the small circle in the top-left of the work area, just above the stage, to edit this movie clip in place.

      This movie clip has an instance name of siren_mc. With its timeline visible, you can see that it's made up of three layers and two frame labels. At the frame labeled On, there's a siren sound on the timeline. When this movie's timeline is sent to that frame label, the sound will play. This will be used to simulate an alarm being turned on. The other frame label on this timeline, Off, contains no sound; when the timeline is sent to that frame, the alarm will cease playing.
    3. Return to the main timeline. On the Lights layer, click the Show Layer button (red X) to reveal a big black box that covers the entire stage. Double-click it to edit this movie clip in place.

      This movie clip has an instance name of lights_mc. With its timeline visible, you can see that it's made up of four layers and five frame labels. This movie clip is used to simulate various light angles in the movie. We'll be scripting our project so that when the burglar moves to a particular area of the screen, the appropriate light will come on.

      For example, if he moves left, the left "light" will come on (frame labeled Left). On the Sound layer, we've placed a sound at each one of the frame labels that gives the audio effect of a big switch being toggled (the light is turning on).

      Now that the introductions are complete, it's time to start scripting!

    4. Return to the main timeline. On the Lights layer, press the Hide Layer button to hide the big black area that is the lights_mc movie clip instance. With the Actions panel open, select Frame 1 on the Actions layer and attach this script:

      message_txt.text = "All Clear";

      var time:Number = 0;

      var size:Number;

      stop ();

      The first line places the text "All Clear" in the message_txt text field as soon as the movie plays. Whenever the timeline is sent back to this frame label, this action will execute again. Knowing this, we can deduce that whenever "All Clear" appears in the message_txt text field, the main timeline is at Frame 1 and the burglar is not present. An understanding of this functionality will prove important in a moment.

      The next two lines of script create the time and size variables, which both hold numeric values. We haven't assigned values to the size variable yet, but some of the scripts we add later will do so.

      The last line stops the timeline from moving past this frame until we instruct it to do so.
    5. With the Actions panel open, select the Tiny button and attach this script:

      on (release) {

      if (message_txt.text == "All Clear") {

      size = 50;

      gotoAndStop ("Burglar");

      } else {

      burglar_mc._xscale = 50;

      burglar_mc._yscale = 50;

      }

      }
      When this button is pressed and released, it will take one of two sets of actions, depending on whether the main timeline is on the frame labeled Clear (no burglar) or the one labeled Burglar (burglar is present). In essence, this script says that if the message_txt text field contains the text "All Clear" (which it will whenever the main timeline is on Frame 1 and the burglar is not present), set the value of the size variable to 50 and move the main timeline to the frame labeled Burglar. At this frame the burglar will be present. The size variable will eventually be used to set the size of the burglar when he first appears in the scene. If message_txt does not contain "All Clear," these actions are ignored and the ones below them are executed instead. This also means that the main timeline is currently at the frame labeled Burglar and the burglar_mc movie clip instance is present in the scene. If this is the case, these actions will scale the vertical and horizontal size of the burglar_mc movie clip instance to 50 percent of its original size.

    6. With the Actions panel open, select the Small button and attach this script:

      on (release) {

      if (message_txt.text == "All Clear") {

      size = 75;

      gotoAndStop ("Burglar");

      } else {

      burglar_mc._xscale = 75;

      burglar_mc._yscale = 75;

      }

      }
      This is just a variation of the script attached to the button in the preceding step. The only difference is that size is given a value of 75 and the two actions that scale the burglar_mc movie clip instance (if present in the scene) scale it to 75 percent.

    7. With the Actions panel open, select the Normal button and attach this script:

      on (release) {

      if (message_txt.text == "All Clear") {

      size = 100;

      gotoAndStop ("Burglar");

      } else {

      burglar_mc._xscale = 100;

      burglar_mc._yscale = 100;

      }

      }
      Once again, this is just a variation of the script attached to the button in the preceding step. The only difference is that size is given a value of 100, and the burglar_mc movie clip instance (if present) is scaled to 100 percent, or its original size.

    8. With the Actions panel open, select the No Burglar button and attach this script:

      on (release) {

      gotoAndStop ("Clear");

      }

      This button does one thing: it moves the main timeline to the frame labeled Clear, where the burglar_mc movie clip instance does not exist. When the timeline is moved back to Frame 1, the actions we set up in Step 4 execute again.

      In summary, the Tiny, Small, and Normal buttons are used to make the burglar appear or to resize him. The button we just configured makes the burglar disappear.

      The rest of the scripting for our project will be placed on the burglar_mc movie clip instance.
    9. With the Actions panel open and the main timeline at the frame labeled Burglar, select the burglar_mc movie clip instance and attach this script:

      onClipEvent (load) {

      startDrag (this, true);

      this._xscale = _root.size;

      this._yscale = _root.size;

      _root.lights_mc.gotoAndStop("bottom");

      _root.mouseXPosition_txt.text = _root._xmouse;

      _root.mouseYPosition_txt.text = _root._ymouse;

      _root.message_txt.text = "ALERT!";

      }

      This set of actions is triggered when this movie clip first appears (load), or when it reappears in the scene as a result of the timeline's being moved to this frame. The first action causes the burglar_mc movie clip (this) to become draggable. The next two actions scale the movie clip's horizontal and vertical size based on the current value of the size variable, which exists on the root (main) timeline. Remember that we set this variable with one of our three buttons (Tiny, Small, or Normal). When one of the buttons is pressed, the size variable is set to a value of 50, 75, or 100 (depending on which button was pressed); the main timeline is sent to the frame containing this movie clip instance; and, on loading, the value of the size variable is used to set the size of the burglar.

      The next action tells the lights_mc movie clip instance to move to the frame labeled bottom. At this label it appears that light is shining from the bottom of the screen. This is just a default setting. We'll make the light_mc movie clip instance a bit more dynamic in a moment.

      The next two actions display the mouse's current x and y positions in the text fields on the root timeline (mouseXPosition_txt and mouseYPosition_txt, respectively).

      The last action displays the text "ALERT!" in the message_txt text field on the root timeline to indicate that the burglar is now present.
    10. Add this script just below the end of the current one:

      onClipEvent (enterFrame) {

      _root.time++;

      _root.timeAmount_txt.text = _root.time;

      _root.timer_mc._rotation = _root.timer_mc._rotation + 1;

      }

      Here, the enterFrame event controls three actions that are executed 24 times a second (because this type of event executes actions at the same rate at which the movie plays).

      The first action uses the time variable on the main timeline (which we created in Step 4), to hold the value of an incrementing number. Using the ++ operator, each time the enterFrame event occurs (24 times a second), the value of this variable is incremented by 1. This syntax is the same as writing the following script:

      _root.time = _root.time + 1;


      The next action is used to display the incrementing value of the time variable in the timeAmount_txt text field.

      The last action rotates the timer_mc movie clip instance by 1 degree, 24 times a second. This will produce the effect of the timer being turned on while the burglar is present.

      NOTE

      Because this script exists on the burglar_mc movie clip instance, it will execute only while that instance is present in the scene.

    11. Add this script just below the end of the current one:

      onClipEvent (mouseMove) {

      if (_root._xmouse > Number(_root.mouseXPosition_txt.text) + 10) {

      _root.lights_mc.gotoAndStop("right");

      _root.message_txt.text = "Intruder is moving East";

      } else if (_root._xmouse < Number(_root.mouseXPosition_txt.text) - 10) {

      _root.lights_mc.gotoAndStop("left");

      _root.message_txt.text = "Intruder is moving West";

      } else if (_root._ymouse > Number(_root.mouseYPosition_txt.text) + 10) {

      _root.lights_mc.gotoAndStop("bottom");

      _root.message_txt.text = "Intruder is moving South";

      } else if (_root._ymouse < Number(_root.mouseYPosition_txt.text) - 10) {

      _root.lights_mc.gotoAndStop("top");

      _root.message_txt.text = "Intruder is moving North";

      }

      _root.mouseXPosition_txt.text = _root._xmouse;

      _root.mouseYPosition_txt.text = _root._ymouse;

      }

      The actions in this script are triggered every time the mouse is moved. An if/else if statement compares the mouse's current position with its last known position, and then acts accordingly. We'll examine the first comparison in the statement; having done that, the rest should be self-explanatory.

      Before we continue, it's important to note that the load event we set up in Step 9 contained two actions that set the text displayed in the mouseXPosition_txt and mouseYPosition_txt text fields based on the x and y positions of the mouse when the burglar_mc movie clip is loaded. We will now use those text values in the comparisons made in this script. Since the information displayed in the fields will be used in mathematical comparisons in our if/else if statement, their values have to be converted to numbers using the Number() function. Thus, the script sees them as numeric values rather than text values.

      The first part of this script states that if the current horizontal position of the mouse (_root._xmouse) is greater than the value of mouseXPosition_txt plus 10, two actions will be executed. By checking the mouse's current position against its last recorded position, we can determine in which direction it's moving. For example, if the current horizontal position of the mouse (_root._xmouse) is 300 and the previously recorded position (as displayed in the _root.mouseXPosition_txt text field) was 200, we know the mouse has moved to the right. In this case, our script would trigger two actions: one to move the lights_mc movie clip instance to the frame labeled right (where the light appears to come from the right part of the stage) and one to display the message "The intruder is moving East" in the message_txt text field. The if statement uses four comparisons to determine whether the mouse has moved right, left, up, or down.

      NOTE

      Keep in mind that although the mouse can move in two directions simultaneously (for example, up and right in a diagonal direction), our script gives single-direction movement precedence. This means that right-left movements are of higher priority than up-down movements. If the mouse moves both left and down, the script will detect only the left movement. The reason is that the if statement first looks to see if the mouse has moved right. If it has, the two actions for dealing with this movement are executed, but no other part of the if statement is executed. If the mouse hasn't moved right, that part of the if statement is ignored, and our script checks whether the mouse has moved left. If it has, the two actions for dealing with this movement are executed, but no other part of the if statement is executed. This same process continues when checking for down and up movements. In essence, once a movement in any single direction has been detected, the rest of the script is ignored. Because the if statement looks for right, left, down, and up movement in that order, if it detects right and left movements first, down and up movements won't matter.

      On a side note, you'll notice that in each comparison we add or subtract 10 from the value of mouseXPosition_txt or mouseYPosition_txt so that the mouse must move at least 10 pixels from its last recorded position before any action will occur. If we didn't do this, the mouse's movement on screen would look like firecrackers going off—that is, visually too intense.

      The last two actions of this script (placed just before the last curly brace in the script) record the current x and y positions of the mouse so that the next time this script is executed (when the mouse is moved), these values can be used in the comparison process of the if statement again. Because these values are placed in the mouseXPosition_txt and mouseYPosition_txt text fields, each time the mouse is moved and these values are updated, the changes are displayed in those fields as well.

      In essence, this script compares the current position of the mouse against its previously recorded position; takes appropriate action based on whether the mouse has moved left, right, up, or down; and records the mouse's current position for the next time the mouse is moved.
    12. Add this script after the current one:

      onClipEvent (unload) {

      _root.time = 0;

      _root.timeAmount_txt.text = _root.time;

      _root.timer_mc._rotation = 0;

      _root.message_txt.text = "All Clear";

      _root.mouseXPosition_txt.text = "";

      _root.mouseYPosition_txt.text = "" ;

      _root.lights_mc.gotoAndStop ("Off");

      }


      This script dictates what happens when this movie clip instance (burglar_mc) is unloaded, or is no longer in the scene (as a result of the main timeline's moving to a frame where the burglar doesn't exist). This occurs when the No Burglar button is clicked and the main timeline is moved to the Clear frame (which is actually Frame 1).

      The actions restore the elements to their original state (that is, before the burglar appeared in the scene). The first one resets the time variable to 0. The next action sets what is displayed in the timeAmount_txt text field to the value of time (making it 0 as well). The next action resets the rotation property of the timer_mc movie clip instance to 0; the action after that displays "All Clear" in the message_txt text field. The subsequent two actions clear the mouseXPosition_txt and mouseYPosition_txt text fields, and the last action moves the lights_mc movie clip instance to the frame labeled Off. This last action turns the scene black again.

    13. Add this script after the current one:

      onClipEvent (mouseDown) {

      this.gotoAndStop("right");

      _root.message_txt.text = "Intruder is confused";

      }


      When the mouse button is pressed anywhere on screen, these two actions are executed. The first sends the burglar_mc movie clip instance (this) to the frame labeled right. At this label, the intruder appears to be looking to his right. In addition, a short audio clip plays of him saying, "Oh, no!" The second action causes the message_txt text field to display "Intruder is confused."

    14. Add this script after the current one:

      onClipEvent (mouseUp) {

      this.gotoAndStop("left");

      _root.message_txt.text = "Intruder is running";

      }


      When the mouse button is released anywhere on screen, these two actions are executed. The first sends the burglar_mc movie clip instance (this) to the frame labeled left. At this label, the intruder appears to be looking to his left. The second action causes the message_txt text field to display "Intruder is running."

    15. Add this script after the current one:

      onClipEvent (keyDown) {

      _root.siren_mc.gotoAndStop("on");

      _root.message_txt.text = "Backup has been called";

      }


      When any key is pressed, two actions are executed. The first sends the siren_mc movie clip instance to the frame labeled on, causing a siren to be heard. The second action causes the message_txt text field to display "Backup has been called."

    16. Add this script after the current one:

      onClipEvent (keyUp) {

      stopAllSounds();

      _root.siren_mc.gotoAndStop("off");

      _root.message_txt.text = "Silent alarm activated";

      }


      When any key is released, these three actions are executed. The first stops all sounds, including the currently playing siren. The second action sends the siren_mc movie clip instance to the frame labeled off (causing the siren to be turned off). The last action causes the message_txt text field to display "Silent alarm activated."

      NOTE

      Because the mouseDown/mouseUp and keyDown/keyUp clip events are attached to the burglar_mc movie clip instance, none has an effect until that instance appears in the scene.

      The scripting of our project is complete.

    17. Choose Control > Test Movie to test the functionality of our project.

      Press one of the buttons on the top-right corner of the stage to make the burglar appear. When he appears, notice how the environment changes. Move him around to see what changes his movement provokes. Press the button to remove him and notice what happens. When the burglar is in the scene, click the mouse or press the Spacebar on the keyboard. Most of our movie's interactivity depends on the burglar_mc instance being present in the scene, showing how introducing a single instance into the scene can change its dynamics completely.

    18. Close the test movie and save your work as ClipEvents2.fla.

      This completes the exercise.