Introduction to Director Key Handling
Before getting to the specific key handling for the game, let's first talk about how to generally handle keyboard input within Director. Loosely speaking, there are three ways to monitor the keyboard from Lingo: primary event handlers, behaviors attached to sprites, and the behaviors that are attached to frames. Let's first look at behaviors attached to either sprites or to a frame, and the events you can use within them.
The reason we're starting with behaviors is because of Director's event hierarchy. Normally, behaviors attached to sprites will receive an event first, followed by behaviors attached to frames, and then any handlers within movie scripts. However, this can be overridden using a primary event handler, as you will see in the next section.There are several handlers and methods with which you can determine what key, or keys, are being pressed. Whenever a key is pressed Director sends a keyDown event. When a key is released, a keyUp event is generated. If you have handlers in place, the events will be captured. Otherwise they will travel down the hierarchy until they are captured or they fall through the bottom.Assuming there is a handler in place to capture the event, you still need a way to determine which actual key is being pressed. For this, Director offers several different methods; which one you use will depend on your need.Examine the following code example:
on keyDown me
Here, whenever a key is pressed, three pieces of data will be traced out to the Message window. Note that all three items are based on Director's new Key object, which is accessed from the _key property._key.key
This property returns the ANSI (American National Standards Institute) value assigned to the key._key.keyCode
This property returns the numerical value of the key, not the ANSI value._key.keyPressed()
This method is unique in how it works, which makes it particularly suited for our needs. Using the method as shown here will result in the ANSI value of the key being traced. But you can also use keyPressed() to determine if a particular key is being pressed by giving the method the key code of the key. As an example, look at the following:
on keyDown me
In this form, the keyPressed() method will return either true or false, indicating whether the particular key (124 is the right arrow key) is being pressed. Don't worry about how to get the codes to use. In the next part of this lesson you will create a small tool MIAW that you can use to find keyboard key data.Using the keyPressed() method is a great way to find out if a particular key is being depressed, but using it as shown will only allow you to check if a single key is being pressed. This is because the method is placed within a keyDown handler, which is only executed when a key is pressed. In some applications, especially games, you will want to see if multiple keys are being pressed at one time. This can be done by getting rid of the keyDown handler, and placing the keyPressed() method within an enterFrame or exitFrame handler instead. This is exactly what you will do later in this lesson, when you add the player's ship to the game.One limitation of trying to handle keyboard input within a sprite script is that only field and text sprites are able to process key events. Trying to enter text into a bitmap sprite doesn't really make sense, so Director won't process key handlers within behaviors attached to other kinds of sprites. This can be remedied by placing the key-handling Lingo within a frame behavior, or by using a primary event handler if you only need to check for single key presses.
Using Primary Event Handlers
Normally, Director's event hierarchy dictates the path an event takes through the system starting at the sprite level and then going to the member, the frame and on down to the movie script level. When an event handler for the event is found, the event is handled, and it stops. However, by defining a primary event handler, you are able to essentially re-order the hierarchy so that a key or mouse press is trapped by the primary event handler first, before any other handlers have a chance to catch it. And unlike typical event handlers that stop an event after handling it, a primary event handler will handle the event and then pass it on, placing it back into the regular hierarchy. Using a primary event handler is a good way to allow specific keys to be checked for immediately and everywhere within your movie. For instance, checking for quit, or something that needs to be available at all times such as a help panel, can easily be handled by using a primary event handler. Let's see firsthand how a primary event handler works.
|1. ||Open the primary_event.dir file from the Lesson12 folder on the CD.This movie simply places the value of the key code into the Message window whenever a key is depressed. A keyDown handler is attached to the field sprite, to the frame, and is also in a movie script. This ensures that no matter where you press a key, the event will be handled.|
|2. ||Play the movie, then open the Message window. Enter some text into the field. Don't press the button to toggle the primary event handler yet.As you type, you will see the key codes of the characters being typed scroll through the Message window. This is because the following behavior is attached to the field sprite:|
on keyDown me
trace("FROM FIELD:" && _key.keyCode)
Every time a key is pressed the key code is traced to the Message window. Note that the pass command allows the event to travel into the field itself. By placing the keyDown handler onto the field sprite, you stop the event from passing to it. Using Lingo's pass method allows the event to pass through the keyDown handler, instead of being trapped by it, as would normally happen. Without using pass here, whatever is being typed would not appear in the field. This way, you can write custom key handlers that only allow certain characters into the field. In fact, this is how you would create a password behavior. You keep track of what's being typed, but instead of placing the character in the field, you place only asterisks.
|3. ||Stop the movie and, in the Score's behavior channel, double-click the script at frame 5 to open the script.The script, which is nearly identical to the one on the field, is:|
on keyDown me
trace("FROM FRAME:" && _key.keyCode)
You never see the FROM FRAME: in the Message window however, because the keyDown event is trapped by the field.
|4. ||Play the movie and then either click the Next Marker button or click in the frame bar, to move the playhead to frame 10. Click on the movie's stage to give it the focus, then type in some text with your keyboard.This time, the key codes appear in the Message window and have the FROM FRAME: label in front of them. Again, because the event is handled by the frame script, it doesn't pass to the handler in the movie script. In fact, you will only see the FROM MOVIE: label if you move the playhead to frame 15, where no other scripts are there to handle the event first.Now, let's see what a primary event handler does.|
|5. ||With the movie still playing, move the playhead back to frame 5 so the field is showing. Press the Toggle Primary Event Handler button, then enter some text into the field.As you enter text you now see the key code put to the Message window twice: first from the primary event handler, and then by the behavior attached to the field.This is what a primary event handler does. No matter where you are in the movie, if a primary event handler is active, it will receive the event first and then pass it on for any other handlers to get it.Let's see how the button toggles the handler.|
|6. ||Stop the movie and right-click the toggle button. Select Script from the context menu.|
on mouseUp me
_global.peh = not(_global.peh)
if _global.peh then
the keyDownScript = "peh"
the keyDownScript = Empty
First the global variable peh is negated using the not() function. This line toggles the state for the button: not true is false, and not false is true. Every time the button is pressed, the not() function changes the variable from true to false, and vice versa.If peh is true, the keyDownScript is set to the handler named peh; otherwise it is set to the Lingo constant Empty. By setting the keyDownScript to empty, you effectively turn the primary event handler off.The peh handler in the movie script is shown here:
trace("FROM Primary Event Handler:" && _key.keyCode)
Besides the keyDownScript primary event handler, there is also a keyUpScript, a mouseDownScript, and a mouseUpScript primary event handler. By setting these to the name of a handler you can use in your movies.Now that you know how to handle basic key presses, let's look at handling special keys such as Shift, Alt/Option, and Ctrl/Command.
Handling Special Keys
You might have noticed while running the primary event handler test movie that no key code appeared in the Message window when you pressed keys such as Shift or Ctrl/Command. You didn't notice? Trust methey didn't appear. This is because these are modifiers for the rest of keys on the keyboard and as such they don't have their own key codesnone that are available for our use, anyway.In order to know if the user is pressing these special keys you need to use the following properties of the Key object:_key.shiftDown
returns true if Shift is being pressed._key.optionDown
returns true when Alt is pressed in Windows, or Option is pressed on the Macintosh. In Windows this will only return true if another key in addition to Alt is pressed._key.commandDown
returns true when the Ctrl key is pressed in Windows, or the Command key is pressed on the Macintosh._key.controlDown
Similar to commandDown, but in Windows only. It's best to just ignore controlDown and use commandDown, as it works cross platform.To test for these keys you use the same method as for the regular keys. Because these keys don't create a keyDown event when pressed, you can use the keyDown handler to test for key combinations like Ctrl+P and others. For instance, the following code placed in a keyDown handler would run the doPrint() handler whenever the Ctrl+P key combo was pressed:
on keyDown me
if _key.commandDown and _key.key = "p" then
There is one small issue you should be aware of. Within the authoring environment Director itself will receive Ctrl/Command and Alt/Option key presses and not let them through to Lingo. This is only when in authoring, though; you can rely on these methods to work in a projector.In order to make use of keys like the arrow keys, backspace, etc., you will need to use their key code values. To make it quick and easy to get these values many developers create a small utility tool that can be accessed at anytime when in Director.