Orchestrating Multiple EventsAs 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.
|
Thursday, December 13, 2007
Orchestrating Multiple Events
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.
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.
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).
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.
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.
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.
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.
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).
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.
-
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.
-
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.
-
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
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.
-
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.";
}
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.
-
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
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.
-
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.
-
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
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.
-
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.
-
With the Scene panel open, click the scene named Playroom.
This scene contains seven layers, named according to their contents.
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.
-
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. 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."
-
With the Actions panel still open, select the card_mc movie clip instance and add the following script:
on (releaseOutside) {
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.
this._x = _root._xmouse;
this._y = _root._ymouse;
}
-
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.
-
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.
-
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.
-
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.
-
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.
-
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.
-
With the Actions panel open, select Frame 2 on the Actions layer and add the script:
_root.date_txt.text = "June 16th";
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.
_root.country_txt.text = "Italy";
_root.caption_txt.text = "The food was excellent!"
-
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";
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.
_root.country_txt.text = "Monaco";
_root.caption_txt.text = "The mountains were amazing!";
-
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.
-
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.
-
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.
-
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.
-
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.
-
With the Actions panel open, select the triangular button on the control panel and add this script:
on (release) {
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.
play ();
}
on (rollOver) {
balloon_txt.text = "Play";
}
on (rollOut) {
balloon_txt.text = "";
}
-
With the Actions panel open, select the square button on the control panel and add this script:
on (release) {
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.
stop ();
}
on (rollOver) {
balloon_txt.text = "Stop";
}
on (rollOut) {
balloon_txt.text = "";
}
-
With the Actions panel open, select the double-triangle button on the control panel and add this script:
on (release) {
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.
gotoAndPlay (1);
pictures_mc.gotoAndStop (1);
warning_txt.text = "";
}
on (rollOver) {
balloon_txt.text = "Rewind";
}
on (rollOut) {
balloon_txt.text = "";
}
-
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.
-
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.
-
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.
-
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.
-
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!
-
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.
-
With the Actions panel open, select the Tiny button and attach this script:
on (release) {
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.
if (message_txt.text == "All Clear") {
size = 50;
gotoAndStop ("Burglar");
} else {
burglar_mc._xscale = 50;
burglar_mc._yscale = 50;
}
}
-
With the Actions panel open, select the Small button and attach this script:
on (release) {
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.
if (message_txt.text == "All Clear") {
size = 75;
gotoAndStop ("Burglar");
} else {
burglar_mc._xscale = 75;
burglar_mc._yscale = 75;
}
}
-
With the Actions panel open, select the Normal button and attach this script:
on (release) {
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.
if (message_txt.text == "All Clear") {
size = 100;
gotoAndStop ("Burglar");
} else {
burglar_mc._xscale = 100;
burglar_mc._yscale = 100;
}
}
-
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.
-
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.
-
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.
-
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.
-
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.
-
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."
-
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."
-
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."
-
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.
-
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.
-
Close the test movie and save your work as ClipEvents2.fla.
This completes the exercise.
-