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

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

Figure 8-14 illustrates the
Star
class's public properties and methods.

Figure 8-14.
The star's public properties

But because the star needs to spin around its center, the
_starImage
needs to be centered. This is easily done with two lines of code that subtract half the star images' height and width from its x and y position. This neatly centers the image.

_star.x = -(_star.width / 2);
_star.y = -(_star.height / 2);

Because the star image is now centered, its spin axis will be its center point. If the star image isn't centered like this, the spin axis will be its top left corner and the spin effect will be lopsided.

Launching the star

When the player presses the space key on the keyboard, the
onKeyDownHandler
sets the star's launched property to true. It does this only if launched isn't already true so that the star isn't launched more than once while it's on the stage.

if(event.keyCode == Keyboard.SPACE)
{
  if(!_star.launched)
  {
    _star.x = _character.x + _character.width / 2;
    _star.y = _character.y + _character.width / 2;
    _star.launched = true;
  }
}

This code also centers the star on the character.

If the star has been launched, the
enterFrameHandler
then runs this code:

if(_star.launched)
{
  //If it has been launched, make it visible
  _star.visible = true;
  //Move it
  _star.y -= 3;
  _star.rotation += 5;
  //Check its stage boundaries
  checkStarStageBoundaries(_star);
  //Check for collisions with the monsters
  starVsMonsterCollision(_star, _monster1);
  starVsMonsterCollision(_star, _monster2);
}
else
{
  _star.visible = false;
}

This code makes the star visible, moves it, rotates it, checks its stage boundaries, and checks for collisions with the monsters. If the launched property is false, this code also makes the star invisible. As you'll soon see, the launched property is set to false when the star hits the stage boundary or any of the monsters.

Checking the star's collisions

Because the star only moves upwards, the code that checks its stage boundaries only needs to check for a collision with the top of the stage. The
checkStarStageBoundaries
method does this:

private function checkStarStageBoundaries(star:Star):void
{
  if (star.y < 50)
  {
    star.launched = false;
  }
}

It sets the star's launched property to false if it hits the top playing field boundary.

The
starVsMonsterCollision
method checks for collisions between the star and the monsters. It takes two arguments: the star and the monster that you want to check for a collision against.

starVsMonsterCollision(_star, _monster1);
starVsMonsterCollision(_star, _monster2);

The method's function definition will only check for a collision if the monster being checked is visible. (If it's invisible, it means it's already been hit three times and has been removed from the game.) If the monster is visible, the code does the following things:

  • Opens the monsters mouth.
  • Adds 1 to the monster's timesHit property.
  • Sets the star's launched property to false.
  • Checks whether the monster has been hit three times; if it has, it calls the
    killMonster
    method.
  • If the monster has been hit three times, it also calls the
    checkGameOver
    method to find out if the game is possibly finished.

Here's the
starVsMonsterCollision
method that does all this work:

private function starVsMonsterCollision
  (star:Star, monster:Monster):void
{
  if(monster.visible
  &&star.hitTestObject(monster))
  {
    //Call the monster's openMouth
    //method to make it open its mouth
    monster.openMouth();
    //Deactivate the star
    star.launched = false;
    //Add 1 to the monster's
    //timesHit variable
    monster.timesHit++;
    //Has the monster been hit
    //3 times?
    if(monster.timesHit == 3)
    {
      //call the killMonster
      //method
      killMonster(monster);
      //Check to see if the
      //game is over
      checkGameOver();
    }
  }
}

This is an interesting bit of code because it changes one property in the star, two properties in the monsters, and calls two methods in the
LevelOne
class.
Figure 8-15
shows how all these connections fit together.

Figure 8-15.
What happens when the star hits the monster

You'll look at the
checkGameOver
method in detail soon, but first take a look at what happens when one of the monsters is hit three times.

Vanquishing the monsters and creating an explosion

If the star hits one of the monsters three times, the
killMonster
method is called. It performs the following tasks:

  • Makes the monster invisible.
  • Creates an explosion object from the
    Explosion
    class and adds it to the stage.
  • Centers the explosion over the monster's current position.
  • Calls the explosion object's
    explode
    method. This makes the explosion image appear and then disappear again after two seconds.

Here's the
killMonster
method that does all this:

private function killMonster(monster:Monster):void
{
  //Make the monster invisible
  monster.visible = false;
  //Create a new explosion object
  //and add it to the stage
  var explosion:Explosion = new Explosion();
  this.addChild(explosion);
  //Center the explosion over
  //the monster
  explosion.x = monster.x -21;
  explosion.y = monster.y -18;
  //Call the exlposion's
  //explode method
  explosion.explode();
}

This is the first time you've seen how you can create an object while the game is in progress. All the other game objects, like
_star
,
_character
,
_monster1
, and
_monster2
, were created when the game was initialized. The explosion objects are created by the
killMonster
method whenever they're needed, like this:

var explosion:Explosion = new Explosion();
this.addChild(explosion);

This new explosion object is
local
to the
killMonster
method. That means that you can only access it inside this method. You can't refer to this new
explosion
object anywhere else in the class. That's just fine because it's just a simple visual effect that you don't need to use anywhere else. You also don't know how many explosion objects you'll need before the game starts, so this method will make a new one whenever you need it, whether that's 1 or 100. You don't need to plan this in advance by creating all the explosion objects when you initialize the game.

Local variables
and objects can only be used inside the method that creates them. You can make a local variable inside a method like this:

var localVariable:VariableType = new ClassName();

Notice that “var” is not preceded by “public” or “private”.

Instance variables
and objects can be used in all the code, anywhere in the class. Instance variables are created in the class definition, like this:

private var _instanceVariable:VariableType = new ClassName();
public var instanceVariable:VariableType = new ClassName();

These variables can be used anywhere in the class, all the time and by any method. If they're declared as public, other classes can access them too. Most of the variables and game objects you've been working with have been instance variables.

Because local variables have a more limited scope, they occupy slightly less space in the Flash Player's memory.

After this new
explosion
object is created, it's centered over the monster's current position.

explosion.x = monster.x -21;
explosion.y = monster.y -18;

Finally, the
explosion
object's
explode
method is called.

explosion.explode();

This makes the explosion image visible for two seconds and then makes it invisible again. All this is done with a timer in the
Explosion
class, and it uses exactly the same technique you used to make the monster open and close its mouth.

Here's the entire
Explosion
class with its public
explode
method that starts the timer that makes the image visible:

package
{
  import flash.display.DisplayObject;
  import flash.display.Sprite;
  import flash.events.TimerEvent;
  import flash.utils.Timer;
  public class Explosion extends Sprite
  {
    //Embed the image
    [Embed(source="../images/explosion.png")]
    private var ExplosionImage:Class;
    //Private properties
    private var _explosion:DisplayObject = new ExplosionImage();
    private var _timer:Timer;
    public function Explosion()
    {
      this.addChild(_explosion);
      _explosion.visible = false;
      _timer = new Timer(2000);
    }
    //Public methods
    public function explode():void
    {
      _explosion.visible = true;
      _timer.addEventListener
        (TimerEvent.TIMER, explosionTimeHandler);
      _timer.start();
    }
    //Private methods
    private function explosionTimeHandler(event:TimerEvent):void
    {
      _explosion.visible = false;
      _timer.reset();
      _timer.removeEventListener
        (TimerEvent.TIMER, explosionTimeHandler);
    }
  }
}

Figure 8-16 illustrates the Explosion class's properties and methods.

Now that you know how all the objects in the game work, let's see how the code determines whether or not the level has been finished.

Figure 8-16.
The Explosion class

Checking for the end of the level

The level is completed when the character has been hit once by the monsters or each of the monsters has been hit three times by the player's star. As you saw in the previous example, when this happens, the code calls the
checkGameOver
method.

private function checkGameOver():void
{
  if(_monster1.timesHit == 3
  && _monster2.timesHit == 3)
  {
    _levelWinner = "character"
    _gameOverTimer = new Timer(2000);
    _gameOverTimer.addEventListener
      (TimerEvent.TIMER, gameOverTimerHandler);
    _gameOverTimer.start();
    _monsterTimer.removeEventListener
      (TimerEvent.TIMER, monsterTimerHandler);
    this.removeEventListener
      (Event.ENTER_FRAME, enterFrameHandler);
  }
  if(_character.timesHit == 1)
  {
    _levelWinner = "monsters"
    _character.alpha = 0.5;
    _gameOverTimer = new Timer(2000);
    gameOverTimer.addEventListener
      (TimerEvent.TIMER, gameOverTimerHandler);
    _gameOverTimer.start();
    monsterTimer.removeEventListener
      (TimerEvent.TIMER, _monsterTimerHandler);
    this.removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
  }
}

Other books

The Eyes and Ears of Love by Danielle C.R. Smith
Critical Judgment (1996) by Palmer, Michael
Roses For Sophie by Alyssa J. Montgomery
Surviving Passion by Maia Underwood
The Four Pools Mystery by Jean Webster