Now let's set about creating a demo for the OneKeyManager class. I have created a very simple FLA file and placed it in a folder of its own. I've also placed in the folder the two classes we talked about on the previous page of this article. In any case, you may download all of these files from the link above.
I have drawn a very simple Player object on the stage. I hope you weren't expecting fancy artwork, but I drew my little "guy" so that it is obvious that he is facing to the right. After finishing the drawing, I selected it and converted it to a MovieClip and called the resulting symbol "Player" (Note that the Player symbol was created with its registration point in the center). Then, in the properties panel, I gave the instance on the stage the instance name of "player."

Next, let's turn our attention the actions panel. Click on frame one of the actions layer, and press F9. Since the two classes were placed in the same folder as the FLA file, they are both available to our timeline code without importing them. That's because the folder that the FLA file is in is always in the classpath.
First, we'll make an instance of the OneKeyManager class for the right arrow key. We'll call the instance rightArrow. When you begin typing:
var rightArrow:OneKeyManager = new OneKeyManager(
...as soon as you type the left parentheses, you will get code hinting telling you what kind of arguments the OneKeyMananger class is expecting. The first one is the stage, the second one is the keyCode. As you keep typing:
var rightArrow:OneKeyManager = new OneKeyManager(stage, KeyList.
...as soon as you type the dot after KeyList, you will get another code hinting window that you can scroll. You can simply pick the word RIGHT from the list. Or if you type the R and the I, it will zero right in on it for you. Press ENTER to accept it. And this is how easy it is to program the right arrow key! Finishing the statement:
var rightArrow:OneKeyManager = new OneKeyManager(stage, KeyList.RIGHT);
We'll stop there, although we optionally could go on to provide the names of the functions we want to use for the pressHandler and / or the releaseHandler. Those functions would have to be written, of course, and if we provided their names here, we could go on to write them. However, if we later decide we want to add those, we can also just use the public setter methods that the OneKeyManager class provides for that purpose, as we'll soon demonstrate. Let's make an instance for the left arrow key too:
var leftArrow:OneKeyManager = new OneKeyManager(stage, KeyList.LEFT);
Now we have two instances, leftArrow and rightArrow. Those instances simply represent those keyboard keys. With just this much established, we can use the isDown functionality. Let's write that into an ENTER_FRAME event hander:
var rightArrow:OneKeyManager = new OneKeyManager(stage, KeyList.RIGHT);
var leftArrow:OneKeyManager = new OneKeyManager(stage, KeyList.LEFT);
this.addEventListener(Event.ENTER_FRAME, loop);
function loop(event:Event):void {
if(rightArrow.isDown) {
player.x += 10;
}
if(leftArrow.isDown) {
player.x -= 10;
}
}
Notice how natural the language in this event handler is! It almost reads like plain English! If the right arrow is down, then do this. If the left arrow is down, do that. You can name your instances whatever you want, whatever word or words you think best describes your keyboard key. Now, let's proceed to write a pressHandler for the left arrow key that makes the player face to the left:
leftArrow.pressHandler = leftArrow_onPress;
This sets the pressHandler for the left arrow to a function named leftArrow_onPress, which is a function we have yet to write, so let's do that now:
leftArrow.pressHandler = leftArrow_onPress;
function leftArrow_onPress(event:KeyboardEvent):void {
player.scaleX = -1;
}
Notice that the function is written like any other keyboard event handler, with an event parameter ready to "catch" the event object passed to it. This is required, as when our class handles the KEY_DOWN event, it calls the function we've set (even though it's outside the class, the class now has a reference to it) and just passes along the same event object it received. This event object is something you may or may not ever use (you already know the event.keyCode, for example), but it is there should you ever need it. I debated about whether to leave it in or not, and decided it didn't hurt anything, and since we should all be used to writing event handler functions, it shoudn't be any problem. You just write this like you would write any others.
Writing a pressHandler for the right arrow key is exactly the same process:
var rightArrow:OneKeyManager = new OneKeyManager(stage, KeyList.RIGHT);
var leftArrow:OneKeyManager = new OneKeyManager(stage, KeyList.LEFT);
this.addEventListener(Event.ENTER_FRAME, loop);
function loop(event:Event):void {
if(rightArrow.isDown) {
player.x += 10;
}
if(leftArrow.isDown) {
player.x -= 10;
}
}
leftArrow.pressHandler = leftArrow_onPress;
function leftArrow_onPress(event:KeyboardEvent):void {
player.scaleX = -1;
}
rightArrow.pressHandler = rightArrow_onPress;
function rightArrow_onPress(event:KeyboardEvent):void {
player.scaleX = 1;
}
When you test the movie, you will find that the little "guy" can move left and right, and that he always faces in the correct direction. And if we wanted to, we could define other things that happen when these same keys are released. You can also see how easy it would be to define more keys. You could easily define another set of keys that do the same thing the left and right keys are doing now. Suppose we wanted to define the "D" key, and make it do the same thing the right arrow key is doing. The command could be:
var dKey:OneKeyManager = new OneKeyManager(stage, KeyList.D, rightArrow_onPress);
Since the rightArrow_onPress function has previously been defined, we can "save a step" by just taking advantage of the OneKeyManager class's constructor, whose third parameter allows us to go ahead and pass in a reference to the function we want to use for a pressHandler. Cool, eh? Let's go ahead and define the "A" key to do the same action as the left arrow:
var aKey:OneKeyManager = new OneKeyManager(stage, KeyList.A, leftArrow_onPress);
Of course, this just makes the new set of keys mimic the first set in terms of the pressHandler. If you want them to move the player, too, you just have to edit the ENTER_FRAME handler and test for the newly defined keys, example:
if(rightArrow.isDown || dKey.isDown) {
The two vertical pipes, are, of couse, the OR operator. The statement is saying that if either the right arrow key is down or the d key is down, then do the following. And likewise, you would have to modify the if statement for the left arrow key to include the a key.
So far we haven't defined any release handlers. But before we do that, let's make a really quick two-frame MovieClip called Arrow Key. I drew a really quick graphic and converted it to a MovieClip symbol, centering its registration point. I edited the inside of it, gave it two frames, and made the second frame's graphic a bit smaller. I dragged out two instances of it, placing one of them upside down using the transform tool. They represent the left and right arrow keys. I gave them instance names of leftKey and rightKey. When I press the left arrow key on the keyboard, the leftKey object will go to its own frame 2, and when I release the key, it will go back to frame 1 again. Likewise the right arrow key.
Next, let's just go ahead and rewrite the code and simplify it. We'll just supply the references to our press and release handlers right in the contructors this time:
var rightArrow:OneKeyManager = new OneKeyManager(stage, KeyList.RIGHT, rightArrow_onPress, rightArrow_onRelease);
var leftArrow:OneKeyManager = new OneKeyManager(stage, KeyList.LEFT, leftArrow_onPress, leftArrow_onRelease);
var dKey:OneKeyManager = new OneKeyManager(stage, KeyList.D, rightArrow_onPress, rightArrow_onRelease);
var aKey:OneKeyManager = new OneKeyManager(stage, KeyList.A, leftArrow_onPress, leftArrow_onRelease);
this.addEventListener(Event.ENTER_FRAME, loop);
function loop(event:Event):void {
if(rightArrow.isDown || dKey.isDown) {
player.x += 10;
}
if(leftArrow.isDown || aKey.isDown) {
player.x -= 10;
}
}
function rightArrow_onPress(event:KeyboardEvent):void {
player.scaleX = 1;
rightKey.gotoAndStop(2);
}
function leftArrow_onPress(event:KeyboardEvent):void {
player.scaleX = -1;
leftKey.gotoAndStop(2);
}
function rightArrow_onRelease(event:KeyboardEvent):void {
rightKey.gotoAndStop(1);
}
function leftArrow_onRelease(event:KeyboardEvent):void {
leftKey.gotoAndStop(1);
}
It should be clear what this code is doing. You can see that you have the option of setting the handlers in the constructor. OR you can use the setter method after the object is already constructed. Further, you could also do some fancy stuff like, for example, dynamically changing pressHandlers. Just set the pressHandler variable equal to a different function! This should be bringing to mind some cool possibilites! Anyway, here's how the code now behaves:
Note: You will have to click on the swf once to give it focus. Then try the left and right arrow keys. Also try the A and D keys. There is no code in place to keep the player from wandering off the stage. I'll leave that as an exercise for the reader.
One final note: When you test your movies in the Flash authoring tool, if you notice some keyboard keys not working, just pull down the Control menu of the flash player (the flash player's Control menu, not flash's Control menu) and select "Disable Keyboard Shortcuts." This will prevent the flash authoring tool from "stealing" the keystrokes you've programmed. For example, pressing the "B" key in the Flash authoring tool is the keyboard shortcut for selecting the "brush" tool. Flash's keyboard shortcuts are active even when your swf is running, so if you've programmed the "B" key to do something in your program, it won't work. You may not notice it, but by pressing the "B" key, all you are doing is selecting the brush tool in Flash. Checking off "disable keyboard shortcuts" fixes it, like I said. If you close the Flash authoring tool and open it again, you will have to select this option all over again--it doesn't stay selected between sessions.
I hope you like this utility and find it useful. Be sure to let me know if you do. Anyway, I intend to start writing more articles and sharing some of my Flash experiments here. These articles will probably be less like tutorials and more like just a description of the experiment, but I think you'll like them, as they will include a lot of "how to" type stuff.
Jody Hall, January 2012