Lab 5: Class Invaders

Here's a rough imitation of the classic Space Invaders arcade game, designed using object-oriented techniques. Click once inside the movie window to set focus, then use the lateral arrow keys to move the launch pointer (arrow at bottom of screen) left or right. Use the Up arrow to fire.

Architecture

In the main movie file, invaderDemo.fla, the Library contains three Movie Clips: the launcher (arrow-shaped pointer at bottom of screen), the invader (a blue disc), and bullet (a black-and-gray star). Each is linked to an ActionScript 2.0 class file.

In this version, 10 instances of the invader Movie Clip are placed on the Stage in the movie's single frame. Eventually we'll learn ways to bypass this step entirely and make all the movie's contents appear on the fly.

Scripting

Here's the class definition for launcher, contained in the text file Launcher.as:

class Launcher extends MovieClip
{
  //EVENT HANDLER METHODS
  function onEnterFrame()
    {
      if (Key.isDown(39) && this._x < 540) this._x +=20;
      if (Key.isDown(37) && this._x > 10) this._x -=20;
      if (Key.isDown(38)) 
        {
          _root.attachMovie('bullet', 'bullet', 
          _root.getNextHighestDepth());
        }
    }

  //**CONSTRUCTOR
  function Launcher(){}
}

A few things to notice here. First, there are no variables defined (we don't use any), no custom functions other than event handlers; also, the constructor for this class is blank, since we don't need to do anything to or with the launcher when it loads.

The sole method (or function) is an enterFrame handler. This chunk of code waits for a key to be pressed, and responds if the key pressed is either left arrow (keycode 37), right arrow (keycode 39) or up arrow (keycode 38). We use the built-in Key object and its isDown() method to perform this detection.

If the Up arrow key has been pressed, we perform an attachMovie() method on the root. This instruction creates a new Movie Clip that is an instance of the Movie Clip bullet defined in the Library. Note that we can thus create a Movie Clip even if it was never dragged from the Library onto the Stage in the initial architecture. Note also that we can create multiple instances of this Movie Clip -- that is, you can press the Up arrow several times in succession and release a stream of projectiles. Each is an instance of bullet.

In case you're wondering what happens to those magic bullets, here's the class code for bullet:

class Bullet extends MovieClip
{
  //EVENT HANDLER METHODS
  function onEnterFrame()
  {
      this._rotation +=10;
      this._y -=50;
      if(this._y < 0) removeMovieClip(this);
  }

  //**CONSTRUCTOR
  function Bullet()
  {
    this._x = _root.launcher._x;
    this._y = 400;
  }
}

Again, no variable definitions or custom functions. We do have some content in the constructor: code that sets the horizontal position of the defender bullet to the current X position of the launcher. This allows targeting. We also set the Y position (vertical) to the bottom of the screen.

The enterFrame handler rotates the bullet, makes it fly upwards 50 pixels at a go, and tests if it is out of the visible range. If so, we execute a removeMovieClip() method on the defender Movie Clip, which removes the object from the current display. This action undoes the attachMovieClip() method.

Finally, here's the class code for the invader objects, which don't do anything all that interesting:

class Invader extends MovieClip
{
  //VAR DEF
  var moveDelay:Number;
	
  //METHODS
  function rePlace()
    {
      this._x = Math.floor(Math.random()*550);
      this._y = -1*(Math.floor(Math.random()*100));
      moveDelay = getTimer() + 
      Math.ceil(Math.random()*1000)+750;
    }
	
  //EVENT HANDLER METHODS
  function onEnterFrame()
  {
    if(getTimer() > moveDelay)
      {
        this._y += Math.ceil(Math.random(10))+10;
        moveDelay = getTimer() + 
        Math.ceil(Math.random()*1000)+750;
      }
		
      if(this._y > 420) rePlace();
		
      if(this.hitTest(_root.bullet))
        {
          rePlace();
          _root.bullet.removeMovieClip();
        }
    }

  //**CONSTRUCTOR
  function Invader()
  {
    rePlace();
  }
}

We define one variable, moveDelay. This variable lets us set a randomized delay time for the invaders' movements.

We also define a method (custom function) called rePlace() that sets the invader offstage top at a randomized X and Y position. This method also assigns a value to moveDelay by referring to a system method called getTimer(). Technically a method of the root object (that is, the main movie), this method returns a value in milliseconds counting from the point at which the main movie began to run. In other words, getTimer() reads a continuous runtime clock. By setting an increment to this reading and recording the incremented value in a variable, we can thus set checkpoints and hold actions until we have reached those points.

That's exactly what we do in the enterFrame handler, whose actions are conditioned on finding a value of getTimer() that is greater (later) than moveDelay. If we've run out the delay clock, the invader moves. Otherwise it does nothing.

Outside the if test (and not subject to its conditions), we check for two possibilities. First, is the invader off screen at bottom? If so, we perform rePlace() to send it back into action. We also check to see if there is a collision between the invader and the bullet. If so, we also perform rePlace().

You'll note that there's no scoring here. Probably we'd want there to be some negative consequence (i.e., a loss of health or life credit) whenever an invader crosses the bottom of the screen.

You can probably think of many other improvements.

Source Files

You'll find the source file invaderDemo.fla and its three class files, Invader.as, Bullet.as, and Launcher.as, on student-iat.ubalt.edu. Look in the idia610Shared directory, and within that, in lab05.


University of Baltimore Logo

Copyright © 2004 School of Information Arts and Technologies