In order to create a fun and interesting game, we need to add some elements that will challenge the player and make them do something. We’ll start by adding asteroids that move down the screen towards the player. Asteroids will form the main hazard in the first draft of our game.

Task Definition

Asteroids in Space Avengers should abide by the following rules;

  • A new asteroid should appear at the top of the screen every few seconds.
  • All asteroids will constantly move down the screen.
  • When an asteroid has disappeared off the bottom of the screen, you will need to delete it to prevent an infinite number of asteroids from appearing in the game!

Later on, we’ll add bullets and a way to destroy the asteroids - but for now we’ll just make the asteroids move down the screen. They will simply move through the player for now - but we’ll move onto making things collide later.

Walkthrough

1. Create a Timer that does ‘something’ every 2 seconds

We’re going to create a rudimentary timer using a variable in our game state. It will work like this;

  1. Create the variable this.asteroidTimer in your create method and set it to 3000. Phaser counts time in milliseconds so 1000 milliseconds (ms) = 1 second (s).
  2. In your update method, subtract the current delta time from the timer using the delta parameter in the update method.
  3. If the timer is zero or less, print out “SPAWN ASTEROID” in your console and reset the timer back to the full time again.

Frame Time: “Frame Time” or “Delta Time” is a term often used in the games industry. It is the amount of time that has passed since the last time update was called. You can use the delta parameter in the update method to get the amount of time (in milliseconds) that has passed since the last time update was called. Normally, this will be exactly the same very frame (1/60th of a second - or 16.6 milliseconds).

Experiment: In your update method try calling console.log(delta); and see what gets printed out.

create() {
    // Existing code
    this.asteroidTimer = 3000;
}

update(time, delta) {
    // Existing code

    this.asteroidTimer -= delta;

    if ( this.asteroidTimer < 0 ) {
        console.log("Create New Asteroid");
        this.asteroidTimer = 3000;
    }
}

At the end of this step, you should have a system which prints the words “Create New Asteroid” in the developer console in Chrome every 3 seconds.

2. Spawning Asteroids

Now that we have a timer system in place that triggers every couple of seconds, we can start spawning asteroids. We have created a basic function for you already that creates a single asteroid, but you will probably want to upgrade it to make the game more fun.

For this stage of this task, you will need to go through the following steps;

  1. Instead of printing “Create New Asteroid”, you should call this.createAsteroid();.
  2. Notice now that all of your asteroids spawn at the same point. In the createAsteroid method, you can use Phaser.Math.RND.between(a, b); to generate a random number between a and b.

createAsteroid() {
    let x = Phaser.Math.RND.between(50, 550);// 100;
    let y = 50;

    let asteroid = this.physics.add.image(x, y, 'asteroid-medium');
    // Existing Code
}

3. Clean Up Old Asteroids

One thing you may have noticed in the createAsteroid() function in the template project is that we call this.asteroidGroup.add(asteroid); at the end of the function. This adds the asteroid to a ‘group’, which allows us to keep track of all of the asteroids we have created in one place.

A group in Phaser is similar (although, not quite the same as) an array. You can use a group to count how many asteroids there are in the game as well as to loop over all over the asteroids and run commands on them.

While the asteroids we create keep moving down the screen, even when they have moved off the screen - they continue to exist (we just can’t see them). They will continue to move down the world that we can’t see forever. Unfortunately, this means that after a few minutes there will be hundreds of asteroids in the game that we will never see again.

The last part of this task is to clean up those asteroids and destroy the ones that have gone off the screen. You can do this by doing the following;

  1. You can keep count of how many asteroids are currently in the game by adding console.log(this.asteroidGroup.countActive()); to your update() function.
  2. Each time you do an update, you should check each of the asteroids to see if they have gone off the bottom of the screen. We can just check whether the ‘y’ coordinate for that object is greater than a certain number.

Hints: You can get an array of all of the asteroids in the game by doing this.asteroidGroup.getChildren(). This returns a normal JavaScript array containing all asteroids in the game. You can then check the ‘y’ coordinate on an asteroid by checking the asteroid.y property of that object. Finally, you can destroy an asteroid with asteroid.destroy().

update() {
    // Existing Update Code

    let asteroids = this.asteroidGroup.getChildren();

    for( i = 0; i < asteoroids.length; ++i ) {
        if ( asteroid[i].y > 1000 ) {
            asteroid[i].destroy();
        }
    }
}

update() {
    // Existing Update Code

    let asteroids = this.asteroidGroup.getChildren();

    asteroids.forEach((asteroid) => {
        if (asteroid.y > 1000) {
            asteroid.destroy();
        }
    })
}

Extensions

  • If you’ve started going for an alternative theme for your game, now would be a good time to go online and find a different image instead of an asteroid for your game.
  • It’s a good idea to make the asteroid’s Y velocity a constant at the top of the file so that it’s easy to change.
  • Even better, you could add a random factor to the asteroid’s Y velocity to mix things up a bit.
  • You can make the asteroid spin while it moves down the screen setting some angular velocity on the sprite asteroid.setAngularVelocity(45.0);. Try setting the angular velocity to a random value so that it spins at a random speed to mix things up.
  • There are lots of different images in the project asset bundle. You could add some variety to your game by selecting one at of those many images at random.
  • To add even more variation to the game, you could also consider changing the size of the asteroids a small amount by setting the asteroid’s scale factor.

Potential Solution

If you have been following the standard solution, your code should look something like this after this task.

create()
{
    this.asteroidTimer = 3000;
}

update(time, delta)
{
    this.asteroidTimer -= delta;

    if ( this.asteroidTimer < 0 ) {      
        this.createAsteroid();
        this.asteroidTimer = 3000;
    }

    let asteroids = this.asteroidGroup.getChildren();

    asteroids.forEach((asteroid) => {
        if ( asteroid.y > 1000 ) {
            asteroid.destroy();
        }
    });

    // Existing Code
}

createAsteroid() 
{
    let x = Phaser.Math.RND.between(50, 550);// 100;
    let y = 50;

    let asteroid = this.physics.add.image(x, y, 'asteroid-medium');
    asteroid.setVelocity(0, 50);

    this.asteroidGroup.add(asteroid);
}