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

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

There are two details I need to point out. First, the
Character
class is extending the
Sprite
class.

public class Character
extends
Sprite

This means that any game objects you make using the
Character
class are actually
Sprite
objects under their skin. The
extends
keyword means that the
Character
class has
inherited
all the properties and methods of the
Sprite
class. It means that you can use all the same properties and methods that you usually use with
Sprite
objects. Properties like x, y, visible, alpha, or methods like
addChild
will all work with any objects that you make with this new
Character
class.

This is an important programming concept called
inheritance
. When you use the
extends
keyword, the new class you're making “inherits” all of the properties and methods of the class you're extending. Inheritance is a key feature of a programming style called Object Orient Programming (OOP). AS3.0 is an OOP language, as is Java, C++, C #, and Objective C.

It also means that you don't have to create a separate
Sprite
object and add the image to it. The image is already wrapped inside a
Sprite
because the
Character
extends the
Sprite
class.

All of this means that
Character
objects will be able do everything that
Sprite
objects can, with the bonus that they display the image of the game character.

But where is the character.png actually being displayed? It's not being displayed on the stage. It's being displayed inside
this
class. That's what this line does:

this.
addChild(gameObjectImage);

The keyword
this
means “this class.” This line of code means that you're adding the
gameObjectImage
to
this
,
Character
, class. The result is that whenever you use a
Character
class object in a game, the character.png image will automatically be displayed. It's part of the class.

Why didn't you use
stage.addChild()
like you've done in other programs? That's because only the application class can add things directly to the stage. The application class, in this case, is
TimeBombPanic.as
. You'll see how it will add a
Character
class object to the stage very soon.

So now you know that the
Character
class just has the job of displaying the character.png image. But what do the
Bomb
,
Box
,
Background
, and
GameOver
classes do? Exactly the same thing: they display the images you designed in the first part of the chapter. In fact, the code in each is almost identical. Take a look at the
Box
class.

package
{
  import flash.display.DisplayObject;
  import flash.display.Sprite;
  public class
Box
extends Sprite
  {
    
//Embed the image
    [Embed(source="../images/box.png")]
    public var GameObjectImage:Class;
    public var gameObjectImage:DisplayObject
      = new GameObjectImage();
    public function
Box
()
    {
      this.addChild(gameObjectImage);
    }
  }
}

The only difference between the
Box
class and the
Character
class is the name and the PNG file that it's embedding. Browse through the other classes and you'll see that they all follow this identical format.

So now that you've got these classes and stuffed your game graphics inside them, how do you use them? You first have to make objects from them, and you can do this in the application class.

Of course you already know how to make objects: with the
new
keyword. You can make an object from the
Character
class like this:

public var character:Character = new Character();

You can then add it to the stage like this:

stage.addChild(character);

You can now use the
character
object anywhere you like in your game, and it will work like any other
Sprite
object you've ever created. But the one bonus is that it will already contain the character.png image.

Where this saves you a lot of work is if you have to make multiple copies of an object. There are 14 boxes in Time Bomb Panic. You don't need to make 14 separate classes for each box. You just need one parent
Box
class and you can make 14 instances (copies) of it. Each of those instances will automatically contain the embedded box.png image. This saves you having to type out dozens of lines of repetitive code.

Here's how you can make multiple box instances using just one
Box
class. First, make a few
box
objects in the application class.

public var box1:Box = new Box();
public var box2:Box = new Box();
public var box3:Box = new Box();

You can add them to the stage like this:

stage.addChild(box1);
stage.addChild(box2);
stage.addChild(box3);

There's not a single Embed metatag in sight!
box1
,
box2
, and
box3
will all contain the box.png image that was embedded into their parent
Box
class.

Do you see now how classes are just “things” in your game?

These five simple classes have just contained images, but you can put anything you like into a class. In the next chapter, you'll see how to put logic code inside them so that you can create objects with very complex, autonomous behavior.

Figure 7-76
illustrates how these object classes work with the application class to produce the images that you can see on the stage.

Figure 7-76
. The application class makes game objects from the game object classes.

Now that you know your five game objects are self-contained classes, let's take a look at the entire
TimeBombPanic
application class, and I'll show you how they've been used in the game.

Looking at the TimeBombPanic application class

I'm going to list the entire
TimeBombPanic
application here so that you have a reference to it for the rest of the chapter. You'll recognize some very familiar code, but a few new things as well. I'll walk you through exactly how all of it works.

package
{
  import flash.display.DisplayObject;
  import flash.display.Sprite;
  import flash.events.Event;
  import flash.events.KeyboardEvent;
  import flash.text.*;
  import flash.ui.Keyboard;
  import flash.events.TimerEvent;
  import flash.utils.Timer;
  [SWF(width="550", height="400",
    backgroundColor="#FFFFFF", frameRate="60")]
  public class TimeBombPanic extends Sprite
  {
    
//Create the text objects
    public var format:TextFormat = new TextFormat();
    public var output:TextField = new TextField();
    public var input:TextField = new TextField();
    public var gameResult:TextField = new TextField();
    //Create the game objects
    public var character:Character = new Character();
    public var background:Background = new Background();
    public var gameOver:GameOver = new GameOver();
    //The bombs
    public var bomb1:Bomb = new Bomb();
    public var bomb2:Bomb = new Bomb();
    public var bomb3:Bomb = new Bomb();
    public var bomb4:Bomb = new Bomb();
    public var bomb5:Bomb = new Bomb();
    //The boxes
    public var box1:Box = new Box();
    public var box2:Box = new Box();
    public var box3:Box = new Box();
    public var box4:Box = new Box();
    public var box5:Box = new Box();
    public var box6:Box = new Box();
    public var box7:Box = new Box();
    public var box8:Box = new Box();
    public var box9:Box = new Box();
    public var box10:Box = new Box();
    public var box11:Box = new Box();
    public var box12:Box = new Box();
    public var box13:Box = new Box();
    public var box14:Box = new Box();
    //Create the timer
    public var timer:Timer;
    //Create and initialize the vx and vy variables
    public var vx:int = 0;
    public var vy:int = 0;
    //The bombsDefused variable that counts
    //the number of bombs collected
    public var bombsDefused:uint = 0;
    public function TimeBombPanic()
    {
      createGameObjects();
      setupTextfields()
      setupEventListeners();
    }
    public function createGameObjects():void
    {
      
//Add the background
      addGameObjectToStage(background, 0, 0);
      //Add the character
      addGameObjectToStage(character, 50, 50);
      //Add the boxes
      addGameObjectToStage(box1, 100, 100);
      addGameObjectToStage(box2, 150, 100);
      addGameObjectToStage(box3, 200, 100);
      addGameObjectToStage(box4, 150, 150);
      addGameObjectToStage(box5, 100, 250);
      addGameObjectToStage(box6, 200, 250);
      addGameObjectToStage(box7, 250, 250);
      addGameObjectToStage(box8, 250, 200);
      addGameObjectToStage(box9, 300, 100);
      addGameObjectToStage(box10, 300, 300);
      addGameObjectToStage(box11, 350, 250);
      addGameObjectToStage(box12, 400, 100);
      addGameObjectToStage(box13, 400, 200);
      addGameObjectToStage(box14, 400, 250);
      //The bombs
      addGameObjectToStage(bomb1, 105, 160);
      addGameObjectToStage(bomb2, 205, 310);
      addGameObjectToStage(bomb3, 305, 260);
      addGameObjectToStage(bomb4, 355, 310);
      addGameObjectToStage(bomb5, 455, 110);
      //Add the gameOver image and
      //make it invisible when the game starts
      addGameObjectToStage(gameOver, 125, 50);
      gameOver.visible = false;
      //Initialize the timer
      timer = new Timer(1000);
      timer.addEventListener(TimerEvent.TIMER, updateTimeHandler);
      timer.start();
    }
    public function setupTextfields():void
    {
      //Set the text format object
      format.font = "Helvetica";
      format.size = 38;
      format.color = 0xFFFFFF;
      format.align = TextFormatAlign.CENTER;
      //Configure the output text field
      output.defaultTextFormat = format;
      output.autoSize = TextFieldAutoSize.CENTER;
      output.border = false;
      output.text = "0";
      //Display and position the output text field
      stage.addChild(output);
      output.x = 265;
      output.y = 7;
      //Configure and display the gameResult Textfield
      format.color = 0x000000;
      format.size = 32;
      gameResult.defaultTextFormat = format;
      gameResult.autoSize = TextFieldAutoSize.CENTER;
      gameResult.text = "You Won!";
      gameOver.addChild(gameResult);
      gameResult.x = 145;
      gameResult.y = 160;
    }
    public function setupEventListeners():void
    {
      stage.addEventListener
       (KeyboardEvent.KEY_DOWN, keyDownHandler);
      stage.addEventListener
       (KeyboardEvent.KEY_UP, keyUpHandler);
      stage.addEventListener
       (Event.ENTER_FRAME, enterFrameHandler);
    }
    public function updateTimeHandler(event:TimerEvent):void
    {
      output.text = String(timer.currentCount);
      //Stop the timer when it reaches 10
      if(timer.currentCount == 10)
      {
        checkGameOver();
      }
    }
    public function enterFrameHandler(event:Event):void
    {
      
//Move the player
      character.x += vx;
      character.y += vy;
      //Stage boundaries
      if (character.x < 50)
      {
        character.x = 50;
      }
      if (character.y < 50)
      {
        character.y = 50;
      }
      if (character.x + character.width > stage.stageWidth - 50)
      {
        character.x = stage.stageWidth - character.width - 50;
      }
      if (character.y + character.height > stage.stageHeight -50)
      {
        character.y = stage.stageHeight - character.height - 50;
      }
      //Box Collision code
      Collision.block(character, box1);
      Collision.block(character, box2);
      Collision.block(character, box3);
      Collision.block(character, box4);
      Collision.block(character, box5);
      Collision.block(character, box6);
      Collision.block(character, box7);
      Collision.block(character, box8);
      Collision.block(character, box9);
      Collision.block(character, box10);
      Collision.block(character, box11);
      Collision.block(character, box12);
      Collision.block(character, box13);
      Collision.block(character, box14);
      //Bomb collision code
      if(character.hitTestObject(bomb1) && bomb1.visible == true)
      {
        bomb1.visible = false;
        bombsDefused++;
        checkGameOver();
      }
      if(character.hitTestObject(bomb2) && bomb2.visible == true)
      {
        bomb2.visible = false;
        bombsDefused++;
        checkGameOver();
      }
      if(character.hitTestObject(bomb3) && bomb3.visible == true)
      {
        bomb3.visible = false;
        bombsDefused++;
        checkGameOver();
      }
      if(character.hitTestObject(bomb4) && bomb4.visible == true)
      {
        bomb4.visible = false;
        bombsDefused++;
        checkGameOver();
      }
      if(character.hitTestObject(bomb5) && bomb5.visible == true)
      {
        bomb5.visible = false;
        bombsDefused++;
        checkGameOver();
      }
    }
    public function checkGameOver():void
    {
      if(bombsDefused == 5)
      {
        gameOver.visible = true;
        gameResult.text = "You Won!";
        character.alpha = 0.5;
        background.alpha = 0.5;
        timer.removeEventListener
          (TimerEvent.TIMER, updateTimeHandler);
        stage.removeEventListener
          (Event.ENTER_FRAME, enterFrameHandler);
      }
      else if(timer.currentCount == 10)
      {
        gameOver.visible = true;
        gameResult.text = "You Lost!";
        character.alpha = 0.5;
        background.alpha = 0.5;
        timer.removeEventListener
          (TimerEvent.TIMER, updateTimeHandler);
        stage.removeEventListener
          (Event.ENTER_FRAME, enterFrameHandler);
      }
    }
    public function addGameObjectToStage
      (gameObject:Sprite, xPos:int, yPos:int):void
    {
      stage.addChild(gameObject);
          gameObject.x = xPos;
      gameObject.y = yPos;
    }
    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;
      }
    }
  }
}

Other books

Bittersweet Hate by J. L. Beck
Fire and ice by Dana Stabenow
Far Tortuga by Peter Matthiessen
Joel Rosenberg - [D'Shai 01] - D'Shai by Joel Rosenberg - [D'Shai 01]
Return to Sender by Kevin Henkes
Be My Lover by Cecily French
Ruby (Orlan Orphans Book 2) by Kirsten Osbourne