In this part of the lesson you'll develop the key-handling code that will move the player's ship around the screen. This will be done in two stages. A behavior on the ship will use two global variables to modify the ship's position within an enterFrame handler. And a behavior attached to the frame will monitor the keyboard and modify the values in the global variables depending on what keys are pressed. Whenever the variables change, the behavior attached to the ship will automatically modify the motion.
Select the internal cast, then double-click the Main Script movie script in member position 1. Add the following two lines of Lingo to the startMovie handler:
These two variables will be used by the ship's behavior to animate it. By setting them to zero initially, the ship will appear without any default motion.
Close the script window and right-click the ship sprite. Select Script from the context menu. Delete the default mouseUp handler that appears and create the following behavior:
property sp on beginSprite me sp = sprite(me.spriteNum) end on enterFrame me sp.loc = sp.loc + point(_global.shipVelX, _global.shipVelY) end
The sp property is created and references the sprite that the behavior is attached to. This makes it quicker to reference the sprite later. Within the enterFrame handler the sprite's loc property is modified by adding it to another point: point(_global.shipVelX, _global.shipVelY). Because these values are both zero initially, the sprite doesn't move.
Here is what happens next : A sprite's loc returns a point indicating where the sprite is on the Stage. As an example, let's say the ship is located at point (60, 200). If you then added point (2, 0) to the sprite's loc, the sprite would be at point (62, 200). It would move two pixels to the right on screen.
Next, you need to create the key handling code that will modify the shipVelX and shipVelY globals.
Name the script move_ship and close the script window. Double-click the script in the behavior channel at frame 25. Leave the existing exitFrame handler as is, and add the following enterFrame handler, along with the declaration for the two globals at the top of the script:
global shipVelX, shipVelY on enterFrame me xDown = false yDown = false --123 back , 124 forward, 125 down, 126 up if _key.keyPressed(123) then xDown = true shipVelX = shipVelX - .05 if shipVelX < -2 then shipVelX = -2 end if if _key.keyPressed(124) then xDown = true shipVelX = shipVelX + .05 if shipVelX > 2 then shipVelX = 2 end if if _key.keyPressed(125) then yDown = true shipVelY = shipVelY + .05 if shipVelX > 2 then shipVelX = 2 end if if _key.keyPressed(126) then yDown = true shipVelY = shipVelY - .05 if shipVelX < -2 then shipVelX = -2 end if if not(xDown) then shipVelX = shipVelX * .95 if not(yDown) then shipVelY = shipVelY * .95 end
This looks awfully long, but the code is really a quite simple. Note how the global keyword is used at the very top of the script, outside of any handlers. By declaring the globals at the top of the script this way, all handlers within the script have access to the globals without having to preface each usage with _global. In some cases using _global is quicker, but if you have a script that will reference the same global many times, it's generally easier to use this form.
Within the enterFrame two local variables, xDown and yDown, are set to false. These are used as "flags" and are set to true whenever one of the cursor keys is pressed. If either the left or right key is pressed, xDown is set to false, and if the up or down cursor keys are pressed, yDown is set to true. These flags are then used by the last two lines of code in the handler. When no key is pressed, and the variables remain false, the global variables shipVelX or shipVelY are multiplied by .95, slowly decreasing their value to zero. With that in mind, let's examine what happens when one of the cursor keys is pressed.
if _key.keyPressed(124) then xDown = true shipVelX = shipVelX + .05 if shipVelX > 2 then shipVelX = 2 end if
If you look at the comment at the top of the handler, you'll know that this conditional is checking to see if the right arrow key is being pressed (the key code for the forward arrow is 124).
If the right arrow is pressed, xDown is set to true and the global variable shipVelX is increased by .05.
Next, the value in shipVelX is tested to see if it is greater than 2. If it is, it is set to 2, thus limiting its maximum value. Remember, the value of this global variable will be picked up by the behavior on the ship sprite and affect its motion accordingly.
If you've been paying attention you might have thought of changing the line: if shipVelX > 2 then shipVelX = 2 to this shipVelX = min(2, shipVelX). That would work, of course work, and is more compact to write, but it's actually a little slower to execute than the if statement. Can you see how this works to produce the ship's basic acceleration and deceleration? Initially, both shipVelX and shipVelY are set to zero by the startMovie handler. Now, let's assume the right arrow key is pressed to make the ship go forward. The conditional test for the right arrow will be true and .05 will be added to the current value of shipVelX. As the key is held down, the value of shipVelX will continue to increase by .05 until it reaches its maximum value of 2.
At the same time, the behavior attached to the ship uses the shipVelX global variable to change the loc property of the ship sprite. As the shipVelX increases while the key is held down, the ship moves faster and faster. As soon as the key is released, the value in shipVelX, or shipVelY, is multiplied by .95 to slowly decrease it down to 0. This way, when the key is released the ship will glide to a stop.
Because the other conditional statements do the exact same thingbut for the other arrow keysthere's no need to discuss them. Instead, let's mention how multiple key presses are handled.
Although you probably didn't realize it, the code is structured to allow multiple navigation keys to be used. For instance, holding down the right arrow moves the ship forward. But holding down the right and down arrows moves the ship diagonally, down and to the right. This is possible because the key monitoring is being done in an enterFrame as opposed to a keyDown handler. With a keyDown handler, the code is executed only when the key is depressed and not again until the key is released and pressed again. Using an enterFrame, the checks happen at each frame update, allowing multiple keys to be tested.
Note that there are limits to how many keys can be tested for simultaneously. Five seems to be the practical limit, and that somewhat depends on how your keyboard is wired. With some keyboards it's possible to know if up to eight different keys are being pressed at onceperfect for that secret key press combo you've been thinking of using.
Close the script window, then rewind and play the movie. Use the cursor keys to move the ship around the screen.
As you press and hold the different cursor keys, the ship responds and moves accordingly. In fact, it can even move right off the screen. You will need to add some tests to the ship's behavior that will keep it on the Stage.
Stop the movie, then right-click the ship sprite. Select Script from the context menu. Add the following four lines of Lingo to the enterFrame handler. Add these lines after the line that is already in place to set the sprite's loc :
if sp.locH < 20 then sp.locH = 20 if sp.locH > 500 then sp.locH = 500 if sp.locV < 5 then sp.locV = 5 if sp.locV > 350 then sp.locV = 350
Where the loc of a sprite returns a point indicating both its horizontal and vertical position, the locH and locV properties return the individual components. These four lines serve to keep the sprite "in bounds" by checking the sprite's position. If the horizontal position (locH) is less than 20, the position is set to 20; this makes it impossible for the ship to go further left than the 20-pixel mark.
Similarly, the top, right, and bottom positions are also checked, ensuring that the sprite will remain on the Stage.
Close the script window, then rewind and play the movie.
While you can move the ship around as before, you can no longer move it off the Stage, or below the ground level.
Stop the movie and then save it.
You're now ready to give the ship some real lifeby arming it. In the next section of this lesson you'll create a system of reusing sprites to simulate a large number of flying bullets.