Open a new Actionscript file. Type the following in to the script pane:
package com.mysite.keyboard { import flash.display.MovieClip; public class KeyMover { private var _clip:MovieClip; public function KeyMover(clip:MovieClip) { _clip = clip; } } }
This just sets up the basic structure of our file, similar to the last example. You already know that you’re going to be passing in the name of a MovieClip, so we import that class. We create a private variable _clip, and in the constructor, set it to be equal to the clip that’s passed as a parameter, like we did before. What’s new here is that we’re going to save this file into a different package we’ll name “keyboard.” So, go to File, Save. Inside the “Save As…” dialog box, navigate to com, then mysite. Create a new folder and call it “keyboard.” Double click the new folder to enter it, then save your file as “KeyMover.as.”
Next, create a new Flash file. Create a simple circular MovieClip symbol and give it an instance name of “ball.” This will be the clip that we move around the screen using an instance of our class. Click on the first frame of the timeline and open the actions panel. Type in the following:
import com.mysite.keyboard.KeyMover; var keyMover:KeyMover = new KeyMover(ball);
This establishes communication between our fla file and the class file, and creates a new instance of our class file. This time, having newfound confidence in our skills, we didn’t bother to trace a message from the constructor to make sure it works. We just know. We’ll leave this fla file for now, and do some more work on our class.
So far all our class does is receives a MovieClip as a parameter. If we want to move that clip with the keyboard, we obviously need to add listeners to listen for keyboard presses and releases. If you’ve programmed these listeners before, you know that they need to be added to the stage. This is because if you add them to the ball, and the ball doesn’t happen to have “focus” in your flash application, they won’t work. So, take my word, we add the keyboard listeners to the stage. Once again, we’ll use the passed in clip to get a reference to the stage. Add these lines to the constructor:
_clip.stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed); _clip.stage.addEventListener(KeyboardEvent.KEY_UP, keyReleased);
The functions referred to, “keyPressed” and “keyReleased” don’t exist yet, and we’ll write them next. But first, since we used the KeyboardEvent class in the above, that class will need to be imported. So add the following line just below the line that imports MovieClip:
And all is well, and we won’t get an error message this time. Hopefully you see a pattern here: every time you want to use a class that resides in a different package, you will have to import it.
Next, let’s go on to write the handler functions. Add them in just under the constructor, and make them private functions. Here’s our class so far with those added in:
package com.mysite.keyboard { import flash.display.MovieClip; import flash.events.KeyboardEvent; public class KeyMover { private var _clip:MovieClip; public function KeyMover(clip:MovieClip) { _clip = clip; _clip.stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed); _clip.stage.addEventListener(KeyboardEvent.KEY_UP, keyReleased); } private function keyPressed(event:KeyboardEvent) { } private function keyReleased(event:KeyboardEvent) { } } }
These functions will get called whenever any key is pressed or released. We’re only interested in the arrow keys, though. So how do you write your functions to only respond to those particular keys? The answer is that the information for which key was pressed or released is contained in the event object that our handler function receives as a parameter, and the property we need is called “keyCode.” So inside our handler, event.keyCode will contain the keyboard code of the key that was pressed or released. We need to test the value of this property so we can tell if the key that was pressed is one of the ones we’re interested in. This value is a number, and if we want to, we can take the trouble to learn what those numbers are. However, there is an easier way.
It so happens that many of the key codes that are most commonly used have already been written into a class for us as constants. All we need to do is import and use this class. This is the Keyboard class (what else?), and it’s located in the flash.ui package (if you didn’t know that, a good place to find it out is in the help files), so add this line to the import statement block:
import flash.ui.Keyboard;
Now, for example, instead of having to know the numeric value for the right arrow key, we can just use the constant Keyboard.RIGHT to test whether a particular keypress is the right arrow key:
if(event.keyCode == Keyboard.RIGHT) { //do something }
This is because the constant Keyboard.RIGHT contains the actual numeric value we need. Others might prefer to just use the numeric values of the keys directly, and you can do that if you want. I prefer to just import the class, use the constants provided, and save myself the trouble of memorizing the numbers.
Next, to keep track of which keys are being pressed, we’re going to create four Boolean variables, and define them at the beginning of our class:
private var rightArrow:Boolean; private var leftArrow:Boolean; private var upArrow:Boolean; private var downArrow:Boolean;
Now, here’s the logic: When the user presses a key, if it’s the right arrow key, set rightArrow to true. When the user releases a key, if it’s the right arrow key, set rightArrow to false. And the same for the other keys. So our handler functions can be written like so (here’s the entire class so far):
package com.mysite.keyboard { import flash.display.MovieClip; import flash.events.KeyboardEvent; import flash.ui.Keyboard; public class KeyMover { private var _clip:MovieClip; private var rightArrow:Boolean; private var leftArrow:Boolean; private var upArrow:Boolean; private var downArrow:Boolean; public function KeyMover(clip:MovieClip) { _clip = clip; _clip.stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed); _clip.stage.addEventListener(KeyboardEvent.KEY_UP, keyReleased); } private function keyPressed(event:KeyboardEvent) { if(event.keyCode == Keyboard.RIGHT) { rightArrow = true; } if(event.keyCode == Keyboard.LEFT) { leftArrow = true; } if(event.keyCode == Keyboard.UP) { upArrow = true; } if(event.keyCode == Keyboard.DOWN) { downArrow = true; } } private function keyReleased(event:KeyboardEvent) { if(event.keyCode == Keyboard.RIGHT) { rightArrow = false; } if(event.keyCode == Keyboard.LEFT) { leftArrow = false; } if(event.keyCode == Keyboard.UP) { upArrow = false; } if(event.keyCode == Keyboard.DOWN) { downArrow = false; } } } }
Now the only thing left to do is write a function that moves the clip. This requires continuous action, so we’ll use the ENTER_FRAME event. The listener for this event needs to be added to the stage as well, so add this line in the constructor, just under everything else:
_clip.stage.addEventListener(Event.ENTER_FRAME, moveClip);
Now, since we can’t use the Event class without importing it, add this import statement to the end of the import statement block:
import flash.events.Event;
Now, we’ll write the moveClip function. Add it to the end of your list of functions:
private function moveClip(event:Event) { if (rightArrow) { _clip.x += speed; } if (leftArrow) { _clip.x -= speed; } if (upArrow) { _clip.y -= speed; } if (downArrow) { _clip.y += speed; } }
Add this line to your variable list at the top of the class:
private var speed:uint = 10;
By creating a separate speed variable, we have one convenient place in the class where we can change the speed and make it apply instantly to all directions. Now the KeyMover class should be fully functional to move the ball around the screen. Be sure to save it, then go back to the fla file, and test your movie. You should get no errors, and be able to move your ball MovieClip around the screen with the arrow keys.
You’ll find, however, that you can also run it right off the edge of the screen. That’s because we didn’t restrict its movement in any way. We could either make the ball stop at the edge of the screen, or we could make it wrap the screen. Let’s add in some code to make it wrap the screen, as that’s kind of a cool effect.