4: Collision Detection

This tutorial requires you to use some of the same techniques adopted in in previous sections.

There are two ‘hit tests’ that we should code, that of the Spaceship colliding with an Enemy, and that of a Bullet striking an Enemy.

We should create a function to deal with the latter (I call this hitEnemy) and embed the code for the former within the moveEnemy function that already exists.

Prerequisites: Please complete Tutorial 3

Variables: Array splicing (removing items from the array)

Tools & Techniques: nested loops, hit tests

There are two 'hit tests' that we should code, that of the player colliding with an Enemy, and that of a Bullet striking an Enemy.

The solution presented here is not the most efficient as the new subroutines repeat iterations through enemies and bullets that are already handled by 'moveBullet()' and 'moveEnemy()'. The reason for this approach is a response to issues with students becoming confused with larger procedures.

Start by calling the new subroutines in the enter-frame subroutine, 'playerMovement', after the previous calls to moveBullet, addEnemy, moveEnemy. Calls as below.

//subroutine to check all bullets and enemies for collisions
	bulletHitEnemy();

	//subroutine to check all enemies and the player for collisions
	enemyHitPlayer();

Now lets create the first of the two subroutines. The first will loop through each instance of Bullet, and for each bullet it will loop through each instance of Enemy to compare every bullet against every enemy.

The comparison is in the form of a hit test called 'hitTestObject' and if true will remove the respective Bullet and Enemy from both the stage and the array.

A 'break' escapes the loops to avoid a runtime error ("Error #1010: A term is undefined and has no properties.") where it cannot find elements in the array because they all shuffled when we removed one element.

function bulletHitEnemy(): void 
{
    //loop through all bullets...
    for (var b: int = 0; b < bullets_arr.length; b++) 
    {
        //...and loop through all enemies for each bullet
        for (var e: int = 0; e < enemies_arr.length; e++) 
        {
            //check each bullet against each enemy for hits
            if (bullets_arr[b].hitTestObject(enemies_arr[e])) 
            {
                //remove the bullet and enemy from the stage
                stage.removeChild(bullets_arr[b]);
                stage.removeChild(enemies_arr[e]);
                //remove the bullet and enemy from their arrays
                bullets_arr.removeAt(b);
                enemies_arr.removeAt(e);
                //escape the for loops without further iterations
                break;
            }
        }
    }
}

For the second subroutine we will loop through each instance of Enemy to compare each with the player instance. The 'hitTestObject' checks for collisions and removes the Enemy instance.

function enemyHitPlayer(): void 
{
    //loop through all enemies and check against player
    for (var e: int = 0; e < enemies_arr.length; e++) 
    {
        if (enemies_arr[e].hitTestObject(player_mc)) 
        {
            //remove the enemy from the stage
            stage.removeChild(enemies_arr[e]);
            //remove the enemy from the array
            enemies_arr.removeAt(e);
        }
    }
}