Foundation Game Design with ActionScript 3.0, Second Edition (50 page)

BOOK: Foundation Game Design with ActionScript 3.0, Second Edition
11.69Mb size Format: txt, pdf, ePub

Let's write a new program to demonstrate all these features.

  1. Create a new ActionScript project called KeyboardControl.
  2. Create an images folder in the project directory and copy the character.png file into it.
  3. Write the following program in the code editor:
    package
    {
      import flash.net.URLRequest;
      import flash.display.Loader;
      import flash.display.Sprite;
      import flash.events.KeyboardEvent;
      import flash.ui.Keyboard;
      import flash.events.Event;
      [SWF(width="550", height="400",
        backgroundColor="#FFFFFF", frameRate="60")]
      public class KeyboardControl extends Sprite
      {
        
    //Create the game character objects
        public var characterURL:URLRequest
          = new URLRequest("../images/character.png");
        public var characterImage:Loader = new Loader();
        public var character:Sprite = new Sprite();
        
    //Create and initialize the vx and vy variable
        public var vx:int = 0;
        public var vy:int = 0;
        public function KeyboardControl()
        {
          
    //Load the image and add the character to the stage
          characterImage.load(characterURL);
          character.addChild(characterImage);
          stage.addChild(character);
          character.x = 225;
          character.y = 150;
          
    //Add event listeners
          stage.addEventListener
            (KeyboardEvent.KEY_DOWN, keyDownHandler);
          stage.addEventListener
            (KeyboardEvent.KEY_UP, keyUpHandler);
          stage.addEventListener
            (Event.ENTER_FRAME, enterFrameHandler);
        }
        public function keyDownHandler(event:KeyboardEvent):void
        {
          if (event.keyCode == Keyboard.LEFT)
          {
            vx = -5;
          }
          else if (event.keyCode == Keyboard.RIGHT)
          {
            vx = 5;
          }
          else if (event.keyCode == Keyboard.UP)
          {
            vy = -5;
          }
          else if (event.keyCode == Keyboard.DOWN)
          {
            vy = 5;
          }
        }
        public function keyUpHandler(event:KeyboardEvent):void
        {
          if (event.keyCode == Keyboard.LEFT
            || event.keyCode == Keyboard.RIGHT)
          {
            vx = 0;
          }
          else if (event.keyCode == Keyboard.DOWN
            || event.keyCode == Keyboard.UP)
          {
             vy = 0;
          }
        }
        public function enterFrameHandler(event:Event):void
        {
          
    //Move the player
          character.x += vx;
          character.y += vy;
        }
      }
    }
  4. Compile the program. Use the arrow keys to move the character around the stage. The movement is now very smooth, and you can also move the character across the stage diagonally'just the kind of character control you're looking for!

You'll find the complete KeyboardControl program in the chapter's source files. Let's take a look at how this new program differs from the first one you wrote.

Moving with velocity

The first things to notice are the two new integer variables,
vx
and
vy
, which store the character's speed'how fast it's going. Actually, I need to be a little more accurate here. It's not really the
speed
of the object that you're storing, but the
velocity
.

Velocity is speed, but it's also direction. This is sometimes a confusing thing for beginners to grasp, so it's worth discussing in more detail. Have a look at this directive:

vx = -5;

vx
refers to the velocity on the x (horizontal) axis. This actually tells you two things. First, 5 is the number of pixels that you want the character to move each frame. You've set the set the frame rate of the SWF file to 60 fps, which means that the object will move 5 pixels each frame, or 300 pixels each second. So that's the first thing: its speed.

Notice the negative sign.

vx = -5;

What does it tell you? Remember that the very left edge of the stage has an x value of 0. As you move to the right, the x value increases. If you move to the left, it decreases. That means that those x values that are negative are actually
pointing to the left.
Positive values
point to the right.
This directive thus tells you the speed and direction, also known as velocity.

5 pixels to the left.

Here's another example:

vy = +5;

vy
refers to the velocity of the object on the y (vertical) axis. The very top of the stage has a y value of 0. As you move down the stage, the values increase. This directive says the following:

5 pixels down.

That's its velocity! Not so hard at all, is it?
Figure 5-3
is a diagram of how positive and negative values can show direction.

Figure 5-3.
You can find the direction of movement by determining whether the x or y values are positive or negative.

If all this seems spectacularly underwhelming and blindingly obvious, good for you! It should be! Now let's see how all this talk of velocity fits in to what's going on in the program.

The choice of the variable names vx and vy has become a programming convention for variables that refer to horizontal and vertical velocities, so they're used in this book. Most programmers who see the variable names vx and vy immediately know what they're referring to. It's just one of those unwritten programming rules that everyone seems to follow, and no one knows why. Of course, you can give these variables any name you like, such as velocityX and velocityY (which are much more descriptive and might make your program easier to read). But, hey, conventions are sometimes a hard thing to knock, so this book sticks with vx and vy.

Using the new keyDownHandler

The
keyDownHandler
has changed slightly from the first program you looked at in this chapter.

public function keyDownHandler(event:KeyboardEvent):void
{
  if (event.keyCode == Keyboard.LEFT)
  {
    vx = -5;
  }
  else if (event.keyCode == Keyboard.RIGHT)
  {
    vx = 5;
  }
  else if (event.keyCode == Keyboard.UP)
  {
    vy = -5;
  }
  else if (event.keyCode == Keyboard.DOWN)
  {
    vy = 5;
  }
}

The if/else statement is no longer changing the character's
x
or
y
properties directly. Instead, it's simply updating the
vx
and
vy
variables with the appropriate velocity. The job of actually moving the object is delegated to the
enterFrameHandler
. More on that in a moment, but first let's take a quick look at this other new event handler:
keyUpHandler
.

Using the keyUpHandler

In the first simple keyboard control program, an event handler called
keyDownHandler
was added to the stage. Its job was to listen for key presses. The funny thing about the
keyDownHandler
is that it only knows when keys are being pressed down, not when they're released. It turns out that knowing that a key is up is just as important for games as knowing that it's down. AS3.0 therefore has a handy little property of the
KeyboardEvent
class called KEY_UP that can tell you this information. You used the KEY_UP property in an event listener that you attached to the stage object in this directive:

stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);

It listens for keys that are being
released
. It sends this information to the
keyUpHandler
so that you can do something useful with it. But why would you want to know whether a key is no longer being pressed?

Think about it this way: you changed the
keyDownHandler
so that when the player of the game presses one of the arrow keys, the velocity of the character is changed by 5 pixels. That's great because when you press one of the arrow keys, you obviously want the character to move. But what about when you stop pressing one of the arrow keys? It would make sense for the character to also stop. However, unless you specifically tell the program this, it doesn't know what you intend, and the character just continues moving endlessly, forever. This wasn't a problem in the simple keyboard control program in which the
keyDownHandler
was changing the character's
x
and
y
properties directly, but now that you're using velocities and delegating the task of actual movement to the
enterFrameHandler
, it becomes a big problem.

The job of
keyUpHandler
is to check whether any of the arrow keys is released and then set the character's velocity to 0. That's what this code does:

public function keyUpHandler(event:KeyboardEvent):void
{
  if (event.keyCode == Keyboard.LEFT
    || event.keyCode == Keyboard.RIGHT)
  {
    vx = 0;
  }
  else if (event.keyCode == Keyboard.DOWN
    || event.keyCode == Keyboard.UP)
  {
    vy = 0;
  }
}

It should be pretty self explanatory, but there's one thing that will be new to you: the
or operator
. It looks like this:

||

It's made up of two
pipe characters
. The pipe character is a vertical line, and you'll find it somewhere on your keyboard near the brace or forward slash keys. Take a good look; it's there somewhere!

The or operator is used inside conditional statements to help you find out whether one thing
or
another thing is true.

Have a look at this line of code:

if (event.keyCode == Keyboard.LEFT
  || event.keyCode == Keyboard.RIGHT)
{...

It literally means this:

If the left arrow key is being pressed,
OR the right arrow key is being pressed,
 do the following.

Releasing either the left or right arrow key sets the horizontal velocity to 0'the character stops moving left or right. Because both conditions have exactly the same result, it makes sense to combine them into one statement with an or operator. It very efficiently saved a few extra lines of redundant code.

Using the enterFrameHandler

The
enterFrameHandler
is what actually makes the character move. It's triggered by an event listener that uses the ENTER_FRAME property of the
Event
class. To use it, you first have to import the
Event
class with this import directive in the class definition:

import flash.events.Event;

You then set up the event listener in the constructor method with this directive:

addEventListener(Event.ENTER_FRAME
,
onEnterFrame);

It follows the same format as the other two listeners, with one important difference: the listener isn't attached to the
stage
object. So what is it attached to? Adding an event listener without attaching it to an object means that the listener is attached
directly to the actual class it's in;
in this case, the
KeyboardControl
class, the actual program you're writing. This won't be of much relevance now, but it will become very important when you start looking at building games using different classes in
Chapter 8
.

When the event listener is triggered, it calls the
enterFrameHandler
.

public function enterFrameHandler(event:Event):void
{
  
//Move the player
  character.x += vx;
  character.y += vy;
}

What this event handler does is very simple: it takes the horizontal and vertical velocities in the
vx
and
vy
variables and assigns them to the character's x and y properties. That makes the object move. Yay!

But wait. What is the event that calls this handler? You know that other events in the program are triggered by keys being pressed or released.
KeyboardEvent.KEY_DOWN
and
KeyboardEvent.KEY_UP
are pretty self-explanatory in that regard, but what kind of event is
Event.ENTER_FRAME
?

Put the kettle on and throw another log on the fire. Here's a little story that might help explain what's going on. The Flash technology was originally designed as a tool for doing animation, which is the art of creating the illusion of motion from nonmoving objects. A lot of the concepts that Flash borrowed came from the animation industry, which used celluloid film to create this illusion. Here, briefly, is how animation with film works:

Film
is a long strip of celluloid (plastic) made up of a series of little squares called
frames
. Each frame contains an image, and each image in a frame is just slightly different from the image in the frame that comes before it. If enough of these slightly different images are flashed in front of a viewer's eyes fast enough, the individual nonmoving images will appear to be a single image that moves. This illusion of motion, which is the basis of all film, video, animation, and even game animation, is called
persistence of vision
.

Other books

Home is a Fire by Jordan Nasser
Shattered Spirits by C. I. Black
Blood and Daring by John Boyko
Perfect Mate by Mina Carter
The Christmas Feast by Bonnie Bliss
Blood on the Sand by Pauline Rowson
Charlotte's Web by E. B. White
Black Spring by Christina Henry
The Columbia History of British Poetry by Carl Woodring, James Shapiro