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. -
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.
-
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.
-
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.
-
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.
-
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.
-
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. -
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.
-
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.
-
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. -
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. -
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. -
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.
-
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.
-
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.
-
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.
-
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. -
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: -
When the mouse button has been pressed, and where it was pressed -
If a key has been pressed, and which one -
If the stage has been resized, and to what new size -
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.
-
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." -
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. -
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. -
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.
-
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. -
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. -
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.
- 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. -
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).
-
Close the test movie to return to the authoring environment and save your work as Listeners2.fla. This completes the exercise and the lesson.
| |
|
No comments:
Post a Comment