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

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

After the bee knows what its target is (the mouse), it calculates the distance between itself and the target. If the distance is less than the
RANGE
value (which is 200), the bee moves.

It moves using a variation of the easing formula we looked at earlier in the chapter. It's a little more complex, however, because you want to limit the bee's speed and the rate at which it turns. Here are the steps the code takes and the formulas it uses to accomplish each task:

  1. The code finds out how far to move the object and assigns these values to
    move_X
    and
    move_Y
    variables:
    var move_X:Number = TURN_SPEED * vx / distance;
    var move_Y:Number = TURN_SPEED * vy / distance;
  2. The values of these new variables are used to modify the velocity:
    _bee.vx += move_X;
    _bee.vy += move_Y;
  3. The bee's new vx and vy properties are used to help it find the total distance required to move:
    var moveDistance:Number
      = Math.sqrt(_bee.vx * _bee.vx + _bee.vy * _bee.vy);
  4. The code then uses this new distance value along with the
    SPEED
    constant to find the correct velocity:
    _bee.vx = SPEED * _bee.vx / moveDistance;
    _bee.vy = SPEED * _bee.vy / moveDistance;

    This is a variation of our easing formula, with
    SPEED
    representing the easing value.

  5. Finally, the code rotates the bee toward the target. This is the same formula we've been using for rotation throughout the book. The addition of + 90 is there to offset the rotation of the bee object by 90 degrees. Without that, the leading edge of the bee would be its right side. (That's because of the way the object was drawn with its “front” being the stinger on the bee's head.) Any objects you use with this code might be oriented differently, so you'll probably want to adjust 90 to another number that you can figure out by trial and error when you see the direction toward which your object rotates:
    _bee.rotation = Math.atan2(_bee.vy, _bee.vx) * 180 / Math.PI + 90;

If the target is
not
within the bee's range, the following directives kick in, which gradually slow the bee down by using friction:

//Apply friction
_bee.vx *= FRICTION;
_bee.vy *= FRICTION;
//Move the bee
_bee.x += _bee.vx;
_bee.y += _bee.vy;

A bit of simple logic, a few careful adjustments to the easing formula, and you have a very effective following behavior.

Running away from the player

It's very easy to create the exact opposite behavior to make the bee run away from the mouse. To see this at work, open the RunAway project folder and run the SWF. You'll see the bee flee from the mouse, as illustrated in
Figure 10-9
.

When I say that this is the opposite behavior, I mean that in the most literal sense imaginable. The application class is exactly the same as the in the previous case, except that the three plus signs have been made negative.

The bee's rotation is negative so that it points in the opposite direction, like so:

_bee.rotation
  = 180 * Math.atan2(_bee.vy, _bee.vx) / Math.PI - 90;

The velocity is also negative, as you can see here:

_bee.x -= _bee.vx;
_bee.y -= _bee.vy;

That's it!

Figure 10-9.
Get too close and the bee flies away.

Rotating and shooting toward the mouse

In the final AI system, the bee turns and fires bullets toward the mouse if the mouse is within range. You'll find this example in the RotateAndShoot project folder, and
Figure 10-10
shows what you'll see when you run the SWF file.

Figure 10-10.
The bee flies toward the mouse and fires bullets at it.

The code that does this is a fusion of the Follow example, with the addition of a bullet-firing system. The bullets are fired using a timer that's started when the mouse comes within range of the bee. Here's the application class that makes this work:

package
{
  import flash.display.DisplayObject;
  import flash.display.Sprite;
  import flash.events.Event;
  import flash.events.MouseEvent;
  import flash.ui.Mouse;
  import flash.events.TimerEvent;
  import flash.utils.Timer;
  [SWF(width="550", height="400",
  backgroundColor="#FFFFFF", frameRate="60")]
  public class RotateAndShoot extends Sprite
  {
    //Embed the images
    [Embed(source="../images/bee.png")]
    private var BeeImage:Class;
    [Embed(source="../images/bullet.png")]
    private var BulletImage:Class;
    //Properties
    private const SPEED:Number = 3;
    private const TURN_SPEED:Number = 0.3;
    private const RANGE:Number = 200;
    private const FRICTION:Number = 0.96;
    private var _beeImage:DisplayObject = new BeeImage();
    private var _bee:GameObject = new GameObject(_beeImage);
    //The bee's angle of rotation
    private var _beeAngle:Number;
    //A timer to fire bullets
    private var _bulletTimer:Timer;
    //An array to store the bullets
    private var _bullets:Array = new Array();
    public function RotateAndShoot()
    {
      //Add the bee to the stage
      stage.addChild(_bee);
      _bee.x = 275;
      _bee.y = 175;
      //Initialize the timer
      _bulletTimer = new Timer(1000);
      _bulletTimer.addEventListener
        (TimerEvent.TIMER, bulletTimerHandler);
      //Add the event listeners
      stage.addEventListener
        (Event.ENTER_FRAME, enterFrameHandler);
    }
    private function bulletTimerHandler(event:TimerEvent):void
    {
      //Create a bullet and add it to the stage
      var bulletImage:DisplayObject = new BulletImage();
      var bullet:GameObject = new GameObject(bulletImage);
      stage.addChild(bullet);
      //Set the bullet's starting position
      var radius:int = 30;
      bullet.x = _bee.x + (radius * Math.cos(_beeAngle));
      bullet.y = _bee.y + (radius * Math.sin(_beeAngle));
      //Set the bullet's velocity based the angle
      bullet.vx = Math.cos(_beeAngle) * 2 + _bee.vx;
      bullet.vy = Math.sin(_beeAngle) * 2 + _bee.vy;
      //Push the bullet into the _bullets array
      _bullets.push(bullet);
    }
    private function enterFrameHandler(event:Event):void
    {
      //Get the target object
      var target_X:Number = stage.mouseX;
      var target_Y:Number = stage.mouseY;
      //Calculate the distance between the target and the bee
      var vx:Number = target_X - _bee.x;
      var vy:Number = target_Y - _bee.y;
      var distance:Number = Math.sqrt(vx * vx + vy * vy);
      if (distance <= RANGE)
      {
        //Find out how much to move
        var move_X:Number = TURN_SPEED * vx / distance;
        var move_Y:Number = TURN_SPEED * vy / distance;
        //Increase the bee's velocity
        _bee.vx += move_X;
        _bee.vy += move_Y;
        //Find the total distance to move
        var moveDistance:Number
          = Math.sqrt(_bee.vx * _bee.vx + _bee.vy * _bee.vy);
        //Apply easing
        _bee.vx = SPEED * _bee.vx / moveDistance;
        _bee.vy = SPEED * _bee.vy / moveDistance;
        //Rotate towards the bee towards the target
        //Find the angle in radians
        _beeAngle = Math.atan2(_bee.vy, _bee.vx);
        //Convert the radians to degrees to rotate the bee correctly
        _bee.rotation = _beeAngle * 180 / Math.PI + 90;
        //Start the bullet timer
        _bulletTimer.start();
      }
      else
      {
        _bulletTimer.stop();
      }
      //Apply friction
      _bee.vx *= FRICTION;
      _bee.vy *= FRICTION;
      //Move the bee
      _bee.x += _bee.vx;
      _bee.y += _bee.vy;
      //Move the bullets
      for(var i:int = 0; i < _bullets.length; i++)
      {
        var bullet:GameObject = _bullets[i];
        bullet.x += bullet.vx;
        bullet.y += bullet.vy;
        //check the bullet's stage boundaries
        if (bullet.y < 0
        || bullet.x < 0
        || bullet.x > stage.stageWidth
        || bullet.y > stage.stageHeight)
        {
          //Remove the bullet from the stage
          stage.removeChild(bullet);
          bullet = null;
          _bullets.splice(i,1);
           i--;
        }
      }
    }
  }
}
Using a timer to fire bullets

A timer is set up to fire bullets every second if the mouse is within range of the bee. The timer is started if it's within range, and stopped if it's out of range, as you can see in the following abridged code from the
enterFrameHandler
:

if (distance <= RANGE)
{
  //…
  _bulletTimer.start();
}
else
{
  _bulletTimer.stop();
}

The
enterFrameHandler
then loops through all the bullets in the
_bullets
array to move them, and removes them from the game if they cross the stage boundaries.

Shooting at random intervals

There's one small modification you can make that will make the bee's shooting behavior much more realistic. As it's been coded, the bee shoots right on cue every 1,000 milliseconds. You can use the
Timer
class's
delay
property to randomize this. Add the following highlighted code to the
bulletTimerHandler
event handler to see the effect:

private function bulletTimerHandler(event:TimerEvent):void
{
  var bulletImage:DisplayObject = new BulletImage();
  var bullet:GameObject = new GameObject(bulletImage);
  stage.addChild(bullet);
  var radius:int = 30;
  bullet.x = _bee.x + (radius * Math.cos(_beeAngle));
  bullet.y = _bee.y + (radius * Math.sin(_beeAngle));
  bullet.vx = Math.cos(_beeAngle) * 2 + _bee.vx;
  bullet.vy = Math.sin(_beeAngle) * 2 + _bee.vy;
  _bullets.push(bullet);
  //Find a random start time for the next bullet
  var randomFireTime:Number
    = Math.round(Math.random() * 1000) + 200;
  _bulletTimer.delay = randomFireTime;
}

The bee now fires randomly between 200 and 1,200 milliseconds.

This AI system is at the heart of what you need to know if you want to create any kind of rotating enemy gun turret for your games. Just substitute another game object for the mouse, and the bee will chase and fire at the object, as we'll see in the next example.

Case study: Killer Bee Pandemonium!

We've made a lot of fun little toys in this chapter, and it doesn't take much work to turn them into a real game. What would happen if we put Button Fairy in the same environment as Killer Bee? We'd get an all-out power shootout between two arch enemies in Killer Bee Pandemonium!, which you'll find in the source files. Run the SWF file and play the game, which you can see in
Figure 10-11
.

Figure 10-11.
Can Button Fairy save the woodland creatures from the grumpy Killer Bee?

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

Other books

Emma's Treasures by Rebecca Joyce
Liverpool Miss by Forrester, Helen
The Musician's Daughter by Susanne Dunlap
Tilly by M.C. Beaton
5 Onslaught by Jeremy Robinson
The Pirates Own Book by Charles Ellms