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

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

Here's how
checkGameOver
works:

  • It finds out who won the game: the monsters or the character. It assigns this to a variable called
    _levelWinner
    .
if(_monster1.timesHit == 3
&& _monster2.timesHit == 3)
{
  _levelWinner = "character"
  //...
}
if(_character.timesHit == 1)
{
  _levelWinner = "monsters"
  //...
}
  • It removes the
    enterFrameHandler
    , which freezes all the action on the stage. If the character has lost, the code sets the character's
    alpha
    to 0.5, which makes it semitransparent.
this.removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
_character.alpha = 0.5;
  • It removes the monster timer's
    TIMER
    event handler so that you stop assigning random directions to the monsters. It's important do this because the monster timer won't quit automatically when the level is finished. You don't want to waste precious CPU power running the timer if you don't need to.
_monsterTimer.removeEventListener(TimerEvent.TIMER, monsterTimerHandler);
  • It starts the
    _gameOverTimer
    , which calls
    gameOverTimerHandler
    .
_gameOverTimer = new Timer(2000);
_gameOverTimer.addEventListener
  (TimerEvent.TIMER, gameOverTimerHandler);
_gameOverTimer.start();

It's the
gameOverTimerHandler
that does the work of displaying the “Level Complete” message or “Game Over” message and informing the application class that the level has been finished. Let's see how this works next.

Ending the level

The
gameOverTimerHandler
introduces some new techniques.

  • It uses the timer's currentCount property to perform a new action every two seconds.
  • It announces that the level is complete so that the application class can load the second level.

Here's the
gameOverTimerHandler
that does this, and I'll explain how it works in detail next.

private function gameOverTimerHandler(event:TimerEvent):void
{
  if(_levelWinner == "character")
  {
    if(_gameOverTimer.currentCount == 1)
    {
      _gameOver.levelComplete.visible = true;
    }
    if(_gameOverTimer.currentCount == 2)
    {
      _gameOverTimer.reset();
      _gameOverTimer.removeEventListener
        (TimerEvent.TIMER, gameOverTimerHandler);
      dispatchEvent(new Event("levelOneComplete", true));
    }
  }
  if(_levelWinner == "monsters")
  {
    _gameOver.youLost.visible = true;
    _gameOverTimer.removeEventListener
      (TimerEvent.TIMER, gameOverTimerHandler);
  }
}
If the monsters win…

Let's first take a look at what happens when the monsters win the game because the code is very simple. The
_gameOverTimer
removes the
gameOverTimerHandler
so that all this code isn't called a second time.

_gameOverTimer.removeEventListener(TimerEvent.TIMER, gameOverTimerHandler);

The code also makes
_gameOver
object's
youLost
subobject visible.

_gameOver.youLost.visible = true;

The
_gameOver
object was added to the game by the
LevelOne
class when the class was initialized.

private var _gameOver:GameOver;
//...
addGameObjectToLevel(_gameOver, 140, 130);

It's been sitting on the stage the whole time, but you couldn't see it because the subobjects that it contains have been invisible. The
GameOver
class contains two subobjects:
youLost
and
levelComplete
. Their visible properties are both set to false when they're added to their parent class. Here's the complete
GameOver
class that does this:

package
{
  import flash.display.DisplayObject;
  import flash.display.Sprite;
  public class GameOver extends Sprite
  {
    //Embed the images
    [Embed(source="../images/levelComplete.png")]
    private var LevelCompleteImage:Class;
    [Embed(source="../images/youLost.png")]
    private var YouLostImage:Class;
    //Private properties
    public var levelComplete:DisplayObject
      = new LevelCompleteImage();
    public var youLost:DisplayObject = new YouLostImage();
    public function GameOver()
    {
      //Add the images to this class
      //and make them invisible
      this.addChild(levelComplete);
      levelComplete.visible = false;
      this.addChild(youLost);
      youLost.visible = false;
    }
  }
}

Figure 8-17 shows the effect that making the
_gameOver
object's
youLost
subobject visible has when the monsters win the game.

Figure 8-17.
Making the “You lost” message visible

So, if the monsters win, that's the end of the game and nothing else happens. Things get a lot more interesting if the character wins.

If the character wins…

When the
_gameOverTimer
is created, it's initialized so that it calls the
gameOverTimerHandler
every two seconds.

_gameOverTimer = new Timer(
2000
);
_gameOverTimer.addEventListener
  (TimerEvent.TIMER,
gameOverTimerHandler
);
_gameOverTimer.start();

As mentioned in
Chapter 7
, timers have a property called currentCount that counts the number of times the timer has run. In this example, the
_gameOverTimer
will increase its currentCount property by 1 every two seconds. The game uses this feature to manage displaying the “Level Complete” message and to load level two.

Then currentCount starts counting from 0 and the timer fires once every 2,000 milliseconds. That means that when it becomes 1, two seconds have already passed. When currentCount becomes 2, four seconds have passed. Here's how it's used to manage the transition from level one to level two:

  • currentCount = 0: There's a two second pause at the end game when the
    enterFrameHandler
    is removed by the
    checkGameOver
    method. The
    checkGameOver
    method also starts the
    _gameOverTimer
    .
  • currentCount = 1: The “Level Complete” message is displayed.
  • currentCount = 2: Two seconds later, the code announces that the level is complete. The application class hears this and loads the game's second level. (The
    _gameOverTimer
    is also reset.)

Figure 8-18 illustrates how the
_gameOverTimer.currentCount
property is managing the last four seconds of the game.

Figure 8-18
. The timer is used to end level one and transition to level two.

Here's the code in the
gameOverTimerHandler
method that actually does this:

if(_levelWinner == "character")
{
  if(_gameOverTimer.currentCount == 1)
  {
    _gameOver.levelComplete.visible = true;
  }
  if(_gameOverTimer.currentCount == 2)
  {
    _gameOverTimer.reset();
    _gameOverTimer.removeEventListener
      (TimerEvent.TIMER, gameOverTimerHandler);
    dispatchEvent(new Event("levelOneComplete", true));
  }
}

You should now understand what this code is doing, except for this one very important line:

dispatchEvent(new Event("levelOneComplete", true));

This bit of code is
dispatching an event
called
levelOneComplete
. It's broadcasting this message to the rest of the game that level one is finished. Any objects who are interested in this message can listen for it and perform some kind of action when they hear this event being broadcast.

The
MonsterMayhem
application class is extremely interested in this event because it needs to know when level one is finished. Let's take a look at the
MonsterMayhem
class again. I've highlighted all the code that adds a listener for the
levelOneComplete
event and the
switchLevelHandler
that takes some action when it hears it.

package
{
  import flash.display.Sprite;
  import flash.events.Event;
  [SWF(width="550", height="400",
  backgroundColor="#FFFFFF", frameRate="60")]
  public class MonsterMayhem extends Sprite
  {
    private var _levelOne:LevelOne;
    private var _levelTwo:LevelTwo;
    public function MonsterMayhem()
    {
      _levelOne = new LevelOne(stage);
      _levelTwo = new LevelTwo(stage);
      stage.addChild(_levelOne);
      stage.addEventListener
        ("levelOneComplete", switchLevelHandler);
    }
    private function switchLevelHandler(event:Event):void
    {
      trace("Hello from the application class! Switch levels!");
      stage.removeChild(_levelOne);
      _levelOne = null;
      stage.addChild(_levelTwo);
    }
  }
}

The
MonsterMayhem
application class listens for the
levelOneComplete
event by attaching an event listener to the stage.

stage.addEventListener("levelOneComplete", switchLevelHandler);

The listener waits until this line of code is run by any object on the stage:

dispatchEvent(new Event("levelOneComplete", true));

As soon as it hears this event, the application class runs its
switchLevelHandler
.

private function switchLevelHandler(event:Event):void
{
  trace("Hello from the application class! Switch levels!");
  stage.removeChild(_levelOne);
  _levelOne = null;
  stage.addChild(_levelTwo);
}

The
switchLevelHandler
does these things:

  • It generates a trace message to let you know that this event is working. This is optional and just used for testing.
trace("Hello from the application class! Switch levels!");
  • It uses the
    removeChild
    method to remove the
    _levelOne
    object from the stage. It also gives the
    _levelOne
    object a value of null, which clears it from the Flash Player's memory.
stage.removeChild(_levelOne);
_levelOne = null;
  • It adds the
    _levelTwo
    object to the stage.
stage.addChild(_levelTwo);

Figure 8-19 shows how the
MonsterMayhem
application class can “hear” when
_levelOne
dispatches an event.

Figure 8-19.
Using events to switch levels

This is the first time you've seen how
removeChild
is used, and it's also the first time you've seen how a class can listen for an event being broadcast by another class. Let's take a slightly deeper look at these two new features.

Other books

Shifting Targets by Austina Love
A Sticky Situation by Jessie Crockett
Dark Horse by Marilyn Todd
A Novel Murder by Simpson, Ginger
First Time Killer by Alan Orloff, Zak Allen
Karen Mercury by The Wild Bunch [How the West Was Done 5]
Complete Atopia Chronicles by Matthew Mather