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

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

Figure 5-8.
Precise screen boundaries using the object's width

The nice thing about using the built-in height and width properties for the character and the stage is that you don't have to know how big either of those things is. This code will work, unchanged, no matter the dimensions of the game character or the stage.

You can find the completed version of this code in the StageBoundaries file in this chapter's source files.

Screen wrapping

Screen wrapping
happens when an object disappears from one side of the stage and then reemerges from the opposite side. This is quite a fun effect and very easy to implement. In fact, the logic that's used to accomplish it is almost exactly the
inverse
of the logic you used to block movement at the stage's edges. Let's try it out!

  1. Change the conditional statements inside the
    enterFrameHandler
    to match the text in bold:
    public function enterFrameHandler(event:Event):void
    {
      //Move the character
      character.x += vx;
      character.y += vy;
     
      //Screen wrapping
      if (character.x + character.width < 0)
      {
        character.x = 550;
      }
      if (character.y + character.height < 0)
      {
        character.y = 400;
      }
      if (character.x > stage.stageWidth)
      {
        character.x = 0 - character.width;
      }
      if (character.y  > stage.stageHeight)
      {
        character.y = 0 - character.height;
      }
    }
  2. Compile the program.
  3. Use the arrow keys to move the character past the edges of the stage. Peek-a-boo! It emerges from the opposite side (see
    Figure 5-9
    ).

    Figure 5-9.
    Screen wrapping

After the detailed look at how to stop an object at the stage edges, I'm sure you can figure out what's going on in this code already. It's almost exactly the same, except for being delightfully backward! It uses the object's width and height to figure out whether the object has completely disappeared off the edge of the stage. As soon as it detects that this is the case, it positions the object on the opposite side of the stage, just beyond the visible boundary. This creates the illusion that the object is trapped on the surface of some kind of cylindrical, never-ending plane. I usually complain about these sorts of things in this book, but this time, it's a blast! Have fun with it! Screen wrapping is, of course, a staple of many old skool games like PAC-MAN and Asteroids, and now you know how to do it if you ever need to.

You can find the complete code for this screen wrapping example in the ScreenWrapping folder in the chapter's source files.

Embedding images

Before you go much further, let's look at an alternate system for loading images into your games. I'm going to show you how to embed images into a program.

This is how you've been loading images into your programs up till now:

First, you created an
URLRequest
and
Loader
object.

public var characterURL:URLRequest
  = new URLRequest("../images/character.png");
public var characterImage:Loader = new Loader();

Then you loaded the image into the
Loader
object

.
characterImage.load(characterURL);

This system of loading images is called
runtime
loading. The images are loaded not when the program is compiled, but when the SWF file runs. It's actually the finished SWF file that is loading these images, not your program. The SWF file reads the paths to PNG files in your images folder and loads the images.

Runtime loading is useful because it means you can change any of the images in your game without having to recompile your program. Just drop different images into the images folder, and the finished SWF file will read the new ones automatically.

However, runtime loading has one fatal flaw. The images load slower than your code runs. That means that your program could start running before any of the images have loaded. This is especially true if you're running ENTER_FRAME events that update your code 60 times per second; it can lead to all sorts of problems.

AS3.0's
Loader
class has a number of built-in methods and properties that allow you to monitor the state of loaded images and initialize the program only when images have finished loaded. This requires quite a bit of additional coding to set up and manage, but, if you're working on a project that requires runtime loading for whatever reason, it may be the only solution. You can find out more about the
Loader
class's properties and methods that allow you to do this in AS3.0's documentation at
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/Loader.html?filter_flash=cs5&filter_flashplayer=10.2&filter_air=2.6

For most games you'll be working on, however, there's a more reliable, simpler, and better way. You can embed images directly into the program. This means that the images are available to the program immediately, before any of the code runs. And it also means that the finished SWF file isn't dependent on an external images folder.

Here are the steps to embedding an image into your program:

  1. Import the
    DisplayObject
    class.
    import flash.display.DisplayObject;

    You add this import statement to the other import statements in your program.

  2. Add these two lines to the class definition:
    [Embed(source="../images/character.png")]
    public var CharacterImage:Class;

    The first line is an
    Embed
    metatag. It tells your program where to look for the image file. (When you embed an image, the path to the file is relative to the AS file, not the SWF file.)

    The second line creates a
    Class
    variable. The image is stored directly in this variable. (Notice that its name begins with a capital letter, which indicates that it's a class.)

    Very importantly, these two lines have to appear together like this, and in this order. You can't separate them or add any other code between them. This is just an odd quirk in AS3.0's syntax.

  3. Create the image object from the
    Class
    variable you created in the previous step.
    public var characterImage:DisplayObject = new CharacterImage();

    This new image object has to be typed as
    DisplayObject
    .

  4. Finally, you need add the image object to the container Sprite in exactly the same way you added your loader objects in previous examples.
    character.addChild(characterImage);

Figure 5-10
illustrates how embedding images works.

Figure 5-10.
Embedding an image into a program

Because of all the problems it solves, embedding images like this is going to be the preferred system for loading images into your games for the rest of the projects in this book. You'll see a practical example of how to embed images in the next section.

You can embed any kind of file, not just image files. In
Chapter 9
, you'll learn how to embed sounds; in Chapter 11, you'll learn how to embed SWF files.

Scrolling

Scrolling
is an effect that allows a player to move about in an environment that is much bigger than the confines of the stage. Like an ancient Chinese scroll being unrolled over a long wooden table, the background moves to allow the character to explore the space beyond the stage edges.

Although it's hard to pick favorites, there's probably very little to learn about game design that isn't in some way embodied in one or the other of the two greatest classic game series of all time:
Super Mario Bros.
and
The Legend of Zelda.
Pretty much anything game designers need to consider about good game design can be found in these two games, and scrolling is no exception.

Super Mario Bros.
uses primarily what's known as
horizontal side-scrolling
. That's when the background moves left or right when the player reaches the left or right edges of the screen. The perspective in horizontal side-scrolling games is usually designed so that it looks as if you're viewing the environment from the side.
The Legend of Zelda
uses
overhead multi-axis scrolling
. In overhead scrolling, you view the environment from above, as if you were a bird flying in the sky and surveying the scene below. With multi-axis scrolling, the player character is free to move in any direction (up, down, left, or right), and the environment scrolls to keep up.

In truth, most games that use scrolling use a combination of these two systems. I'll first show you the more complex of the two, multi-axis scrolling, and finish the chapter with a quick look at horizontal side scrolling. Once you're comfortable with the scrolling techniques covered here, you'll be able to implement any combination of these two systems.

The first thing you need to implement in the scrolling system is some kind of background scene that is much bigger than the stage. In this example, you'll use a very large image.

  1. Find a very large image that you think might be suitable for your scrolling system. Any picture with a width and height greater than 1,000 pixels should work well for this example. I decided to give my hard-working little cat character a holiday in space: a journey to one of Mars's moons, Phobos. Lucky for me, NASA maintains a large collection of copyright-free photos, including extremely high-resolution images of Phobos, which I was able to download. (To download your own high-resolution scenes from space, visit
    http://photojournal.jpl.nasa.gov/
    . Any images labeled Full Resolution are big enough.)
  2. Rename your downloaded photo to background. Be careful; this is probably a JPEG image with a .jpg file extension. If that's the case, you'll need to use the file name “background.jpg” in the sample code that follows.
  3. Create a new ActionScript project called BasicScrolling.
  4. Create an images folder in the BackgroundScrolling project directory and copy your background and character images into it.
  5. Write the following program in the code editor. (You'll find this finished code in the BasicScrolling folder in the chapter's source files.)
    package
    {
      import flash.display.Sprite;
      import flash.display.DisplayObject;
      import flash.events.KeyboardEvent;
      import flash.ui.Keyboard;
      import flash.events.Event;
      [SWF(width="550", height="400",
        backgroundColor="#FFFFFF", frameRate="60")]
      public class BasicScrolling extends Sprite
      {
        
    //Embed the background image
        [Embed(source="../images/background.png")]
        public var BackgroundImage:Class;
        public var backgroundImage:DisplayObject
          = new BackgroundImage();
        public var background:Sprite = new Sprite();
        
    //Embed the character image
        [Embed(source="../images/character.png")]
        public var CharacterImage:Class;
        public var characterImage:DisplayObject = new CharacterImage();
        public var character:Sprite = new Sprite();
        
    //Create and initialize the vx and vy variables
        public var vx:int = 0;
        public var vy:int = 0;
        public function BasicScrolling()
        {
          
    //Add the background
          background.addChild(backgroundImage);
          stage.addChild(background);
          background.x = -1325;
          background.y = -961;
          
    //Add the character
          character.addChild(characterImage);
          stage.addChild(character);
          character.x = 225;
          character.y = 150;
          
    //Add the 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 background
          background.x -= vx;
          background.y -= vy;
          
    //Check the stage boundaries
          if (background.x > 0)
          {
            background.x = 0;
          }
          if (background.y > 0)
          {
            background.y = 0;
          }
          if (background.x < stage.stageWidth - background.width)
          {
            background.x = stage.stageWidth - background.width;
          }
          if (background.y < stage.stageHeight - background.height)
          {
            background.y = stage.stageHeight - background.height;
          }
        }
      }
    }
  6. Remember, you may have to change “background.png” to “background.jpg” If you used a JPEG file.
    [Embed(source="../images/background.jpg")]
  7. Compile the program. Move the character around the stage with the arrow keys, and you'll see that you can fly across the surface of Phobos! (See
    Figure 5-11
    .)

    Figure 5-11.
    A holiday in space!

Other books

Becoming Holyfield by Evander Holyfield
My Alien Love by Boswell, LaVenia R.
Circle of Six by Randy Jurgensen
Awaken by Bryan, Michelle
An Act Of Murder by Linda Rosencrance
Weddings Can Be Murder by Connie Shelton
The Celestial Kiss by Celine, Belle