Arrow Keys for Game Play
May 17, 1999
by Pat McClellan
Dear Multimedia Handyman,
How do I make it so that you can move an object by pressing the Up, down, right, and left keys?
-DuK-
Dear DuK,
This is a good, simple task for learning some basics in Lingo. What you're describing involves the following:
- Sensing that a key was pressed and released
- Finding out which key it was
- Moving a particular sprite a certain number of pixels in the appropriate direction.
Download the sample movie in either Mac or PC format.
So, let's start with the key press. What we want to do is create a movie script (not a behavior) which will "notice" all the key presses and check them to see if it's one of the arrow keys. First, in the startMovie script, we need to assign a custom handler to the keyDownScript and another to the keyUpScript. Since I assume you're going to want the sprite to keep moving as long as the key is held down, we're going to have to monitor whether the key has been released or not. I'll use a global variable called gKeyState to keep track of that. In this startMovie script, let's initialize the gKeyState variable and set it to #released.
on startMovie global gKeyState set the keyDownScript to "arrows" set the keyUpScript to "releaseKey" set gKeyState = #released end
The keyDownScript is set to a handler called "arrows", and the keyUpScript is set to a handler called "release". My idea here is that the keyDownScript will start the motion by setting the gKeyState to #pressed, and the keyUpScript will stop the motion by setting gKeyState to #released. Whenever gKeyState is not #released, then a message will be sent to the sprites to move.
I know that when you're playing a game like this, you want to be able to shift directions quickly -- sometimes overlapping the keypresses. So, we'll want to allow for some "slop". For example, assume that we're pressing the left arrow and the sprite is moving left, because gKeyState is #pressed. Now we quickly press the right arrow without first releasing the left arrow. The sprite starts moving right, but as soon as the left key is release, the keyUpScript ("releaseKey") will reset gKeyState to #released and the motion will stop -- even though we're still holding down the right arrow key.
In order to allow for some overlap of keys, I decided to create a third possible value for gKeyState: #secondPress. I set up an if-then-else statement in the "arrows" handler that checks gKeyState. If no key is pressed (#released), then it sets gKeyState to #pressed. Else, it sets the gKeyState to #secondPress. It also checks the keyCode, and if the keyCode is one of the arrow keys, then it sets another global variable (gKey) to #left, #right, #down, or #up. (This handler can go right below the startMovie script, in the same cast member.)
on arrows global gKeyState, gKey if gKeyState = #released then set gKeyState = #pressed else set gKeyState = #secondPress end if case the keyCode of 123: set gKey = #left 124: set gKey = #right 125: set gKey = #down 126: set gKey = #up end case end
The keyUpScript handler seen below ("releaseKey") does a similar if-then-else check on the gKeyState. If gKeyState is #pressed, then we know that only one key was down (otherwise gKeyState would be #secondPress) so we set gKeyState to #released and motion will stop. The other possibility is that 2 keys had been pressed and now one had been release. That means gKeyState was #secondPress, in which case we'll set gKeyState back to #pressed. (I know all of this is a bit confusing, but you really do need it in order to have quick response that allows some overlap.)
on releaseKey global gKeyState, gKey if gKeyState = #pressed then set gKeyState = #released else set gKeyState = #pressed end if end
So far, we haven't done anything that moves sprites. All we've done is set the gKeyState and check to see which key was pressed. Now comes the good part. The following exitFrame handler should be a movie script -- it can go in the same castmember as all the other scripts we've covered so far. Since it's a movie script, it will be executed every exitFrame of your entire movie. But, as you'll see, if the gKeyState is #released, it does literally "nothing". However, if gKeyState is either #pressed or #secondPress, then it sends a message to all sprites, calling a handler named "keyPress" and telling the sprites which key (gKey).
on exitFrame global gKeyState, gKey if gKeyState = #released then nothing else sendAllSprites(#keyPress, gKey) end if end
That takes care of watching the key up and key down and which key part. It also sends out a message. Now we need to create a behavior which will receive the message from the exitFrame handler, and then move its sprite accordingly. Since this is for a game, I'll assume that you might want to vary the speed at which the sprites move. So we'll have a speed property, which translates to how many pixels per move the sprite will travel.
-- keyMover Behavior -- copyright © 1999, ZZP Online, LLC -- free use for readers of property pSpeed, pSprite on getPropertyDescriptionList me set pdlist to [:] addprop pdlist, #pSpeed, [#comment:"Pixels ¬ per move:", #format:#integer, #default:2] return pdlist end getPropertyDescriptionList on beginSprite me set pSprite = the spriteNum of me end on keyPress me, direction set myLocH = the locH of sprite pSprite set myLocV = the locV of sprite pSprite case direction of #left: set the locH of sprite pSprite = ¬ myLocH - pSpeed #right: set the locH of sprite pSprite = ¬ myLocH + pSpeed #up: set the locV of sprite pSprite = ¬ myLocV - pSpeed #down: set the locV of sprite pSprite = ¬ myLocV + pSpeed end case end on setSpeed me, speed set pSpeed = speed end
Notice that handler called "on keypress me". That's what receives the message from the exitFrame handler. When called, it moves its sprite left, right, up or down by an increment of pSpeed pixels.
The final little handler is called "on setSpeed me". It doesn't do anything in my demo, but in your game, you can change the speed of a sprite simply by saying...
sendSprite (5, #setSpeed, 8)
In this example, I reset the speed of sprite 5 so that it now moves 8 pixels per move. These are the basics, which I hope you'll tear apart and adapt to meet your own needs.
One final note... the arrow keys are "reserved" by some browsers for browser operations, so for Shockwave, it's a better idea to use standard letter keys. In fact, my demo movie above may not work on some of your browsers for this very reason. You can try using the j, k, l, and i keys instead.
Copyright 1997-2024, Director Online. Article content copyright by respective authors.