2: Coding Projectiles

This tutorial builds on Part 1 of the six-part tutorial series on building a Space Shooter. In this section we will create a projectile called 'Bullet' and fire from the player's location across the stage.

Prerequisites: Please complete Tutorial 1 first.

Variables: Arrays (multiple values denoted by an index).

Tools & Techniques: creation of object instances from your own classes (symbols), array splicing.

We are going to start by creating a Bullet symbol, press Ctrl-F8, name it ‘Bullet’, ensure Type is set to ‘Movie Clip’ and select the ‘Export for ActionScript’ checkbox. This will allow us refer to the Class in our code.

Draw something that resembles a bullet...or some kind of laser beam. Again I zoomed to 800% but made the shape smaller than the spaceship. This time make sure the bullet is to the right of the crosshair.

These projectiles are quite light and don't show up well against the white. This is because we intend to change the background to black (or dark navy if you prefer).

On your main timeline, with nothing else selected, the properties will be those of the application and will include a stage color property. Change this by clicking on the color and selecting a new one from the palette that appears (or using the eye-dropper that appears too).

Go back to the stage (‘Scene 1’) and back to the actions in frame 1 of the actions layer.

 

The following global variable declarations will need to be added (its best to place all global variables at the top of your code so you can find them).

 

These variables will allow for spacebar input, set the speed of the bullets, and store each bullet object in an array so we can later refer to it. The last variable, 'cooldown' will slow the rate of fire down.

var spaceBar:Boolean = false;

var bulletSpeed:int = 15;
var bullets_arr:Array = [];
var cooldown: int = 0;

We should also set/reset these values inside our 'initialise' subroutine. So place this code at the end of the procedure (inside the braces).

spaceBar = false;

bulletSpeed = 15;
bullets_arr = [];
cooldown = 0;

In the keyDownHandler and the keyUpHandler subroutines, within the SWITCH-CASE statements, add the following sections of code within their respective switch statements.

 

They are best placed after the last 'break;' and before the two close braces '}'.

// inside function keyDownHandler, and between the switch(event.keyCode) braces
case Keyboard.SPACE:
    spaceBar = true;
    break;
// inside function keyUpHandler, and between the switch(event.keyCode) braces
case Keyboard.SPACE:
    spaceBar = false;
    break;

The playerMovement subroutine needs to now create the bullets when the spacebar is pressed and when the cooldown has reached (or decreased below) zero). If conditions are right (spacebar is down and cooldown is zero or below) then the addBullet subroutine is called and the cooldown is raised to 8.

 

The playerMovement subroutine runs every frame, so any code not encased in an if statement will run 30x per second (based on 30 fps). Beneath the previous if statements and still inside the playerMovement subroutine we will call moveBullet and decrease cooldown by 1.

 

// fire bullets
if (spaceBar && cooldown <= 0) 
{
    addBullet(player_mc.x, player_mc.y);
    cooldown = 8;
}

//subroutine to move all bullets
moveBullet();

//decrement/decrease cooldown by 1
cooldown--;

At the end of the last subroutine , create another below it to generate new bullets. It has parameters that are passed to it when called. The parameters ‘startX’ and ‘startY’ are passed the values from player_mc’s x-y coordinates in the subroutine above. This will allow the bullet to be created in front of the spaceship.

 

A new 'object instance' is declared like a variable, but based on our class, Bullet. We set its x-y coordinates to match that of the spaceship before adding it as a CHILD to the stage.

 

Finally we store the instance in an array so we can keep track of how many bullets we have on the stage.

function addBullet(startX, startY):void
{
    //declare an object instance from the bullet Class
    var b:Bullet = new Bullet();

    //set the new bullet's x-y coordinates
    b.x = startX;
    b.y = startY;

    //add the new bullet to the stage
    stage.addChild(b);

    //store the object in an array
    bullets_arr.push(b);
}

The next subroutine includes an iteration statement called a FOR LOOP. This cycle moves through each of the bullets in the array.

 

For each bullet, the object is moved at the speed stored in ‘bulletSpeed’. As we have limited the number of bullets allowed on stage, when they move from visible sight they are removed from the stage and from the array.

function moveBullet():void
{
    //loop through all instances of the bullet
    //loop from '0' to 'number_of_bullets'
    for (var i:int = 0; i < bullets_arr.length; i++)
    {
        //move the bullet
        bullets_arr[i].x += bulletSpeed;

        //if the bullet flies off the screen, remove it
        if(bullets_arr[i].x > stage.stageWidth)
        {
            //remove the bullet from the stage
            stage.removeChild(bullets_arr[i]);

            //remove the bullet from the array
            bullets_arr.removeAt(i);
        }
    }
}

Arrays - One Dimensional Arrays

A one-dimensional array is a variable with a single list of values. These can have a datatype, such as an integer array will allow for multiple whole number values. Our arrays store objects, specifically they store movie clip symbols.

When we declare an array in ActionScript 3, we must instantiate it like this:

var myArr:Array = new Array();

We can assign some values of the array when we declare it, like this:

var numberArray:Array = new Array(1, 2, 3);
var letterArray:Array = new Array("a", "b", "c");

Each element of an array can be assigned or retrieved by including its index. The index starts at 0 by default and to replicate the effect of the letterArray above we could write it like this:

var letterArray:Array = new Array();
letterArray[0] = "a";
letterArray[1] = "b";
letterArray[2] = "c";

We can also use variables in place of the index value like this:

var letterArray:Array = new Array("a", "b", "c", "d", "e");
var index:int = 2;
var value:int =  letterArray[index];
// value = "c"

Array Properties

length - returns the length of the array. Both numberArray and letterArray above have length of 3.

var howLong:int = numberArray.length();
// howLong= 3

Array Functions

Lets assume we have numberArray as defined above for these examples. Values after the statement are written as comments after //.

push() - passes value within brackets as a new value at the end of the array. Returns the new length of the array if required (we don't use this feature in this tutorial).

var num:int = 5;    // num = 5
numberArray.push(4);    // numberArray = 1, 2, 3, 4
numberArray.push(num);    // numberArray = 1, 2, 3, 4, 5

pop() - removes last item in the array and returns its value.

var num:int = numberArray.pop();
// num = 3, numberArray = 1, 2

shift() - removes first item in the array and returns its value (similar to pop() but takes first item not last)

var num:int = numberArray.shift();
// num = 1, numberArray = 2, 3

removeAt(index) - removes element at the index location and returns its value.

var num:int = numberArray.removeAt(2);    // numberArray = 1, 3

splice(index, n, replacements[optional]) - removes a number of elements, n, starting at the index location and returns an array of values that were removed. An optional list of replacement values is permitted.

var num:int = numberArray.splice(2, 1);
// numberArray = 1, 3

reverse() - reverses the order of the array.

numberArray.reverse();
// numberArray = 3, 2, 1

Iteration - For Loop

For loops can run statements repeatedly until an expression evaluates to false. This kind of loop is useful for looping through each element of an array and for other applications in which you know in advance how many times you want the loop to iterate.

    for (initialiser; condition; iterator)
    {
        statements;
    }

To loop through every element of an array we can use the length property to know how many times to repeat a set of statements. Consider an array of 5 values, the array's length is 5. We would not run through indices 1 to 5, instead we run through 0 to 4 (as arrays start at index 0). The following statement prints each element of the array to the Outputs window.

var letterArray:Array = new Array("a", "b", "c", "d", "e");
for (var i:int = 0; i < letterArray.length; i++)
{
    trace(i + " = " + letterArray[i]);
}
// 0 = a
// 1 = b
// 2 = c
// 3 = d
// 4 = e

Look at the 3 parts of the for loop:

var i:int = 0    : Initialiser, declares the variable i as an integer assigned the value of 0. The variable can be declared before the loop and simply assigned a new value here. The letter i is commonly used for the integer in a for loop, but it can be any unique identifier. If you have more than one loop in a subroutine then they must each use different variable identifiers, so it is common to use j then k as they follow i alphabetically.

i < 5    : Condition, loop will continue until the expression is false, i.e. when i is equal to (or greater than) 5. The condition is checked at the start of each loop.

i++   : iterator, use either ++ to increment or -- to decrement the variable by 1 (occurs at the end of each loop, before the next condition is checked.