Project - Asteroids
Part 6 - Multiple lives; Keeping score; Levels

Now that we're starting to get some of the basic game-play down, let's add build in multiple lives, as well as a scoring system.

6.1. Multiple Lives

Currently, we only have one life in the game—if an asteroid crashes into us, the game is over. Let's set it up so we have three lives before the game quits.

  1. If we're going to keep track of the user's lives we're going to need a counter. In the AsteroidsGame tab, at the top, declare an instance variable for this purpose:
  2. int lives;
  3. In the setup() method, initialize the lives to 3
  4. lives = 3;
  5. In the draw() method, the game will continue to be run just as before. We only want to be looping through that method, however, if we haven't lost all our lives. Let's check for that possibility right at the beginning of draw():
    if (lives == 0) { noLoop(); } . . .
    Otherwise, we'll continue through the loop as before.
  6. In the previous version, we used a noLoop() instruction to stop the game when the spaceship collided with an asteroid. Let's change that instruction as well. When an asteroid collides with the ship, rather than having the game stop, we will:
    1. Subtract one from the number of lives
    2. Create a new Spaceship object which will start at the middle of the screen again.
    3. Create a new ArrayList of random Asteroid objects to reset those.
    4. Clear out all the missiles to reset those.

    Here's how I did it:

    s = new Spaceship(); asteroids = new ArrayList<Asteroid>(); for (int j = 0; j < 10; j++) { asteroids.add(new Asteroid()); } missiles = new ArrayList<Missile>();
    Try playing this version of the program a few times to see if it works the way you want it to.

6.2. Displaying multiple lives

We need to somehow communicate to the user that they have multiple lives to work with. One standard way of indicating that is by displaying a spaceship-shaped icon in the upper-left corner of the screen, one icon for each life that is left.

Although they're not going to be used as actual moving spaceships, we do have the ability to place a spaceship on the screen and show it. We could have a short ArrayList of ships, actually, and show them as needed.

  1. Declare an ArrayList of Spaceships that will be used for our "lives icons."
  2. ArrayList<Spaceship> livesIcons;
  3. Initialize those Spaceship instances with locations that are up in the left corner of the screen.
  4. livesIcons = new ArrayList(); for (int i = 0; i < lives - 1; i++) { livesIcons.add(new Spaceship()); livesIcons.get(i).setX(40 * i + 60); livesIcons.get(i).setY(60); }
  5. In the draw() loop, let's include a short loop that goes through to display each of the Spaceship icons that we've set up.
  6. for (Spaceship life : livesIcons) { life.show(); }
  7. Finally, if we suffer an asteroid collision and lose a life, we'll need to remove the last of those icons so that it isn't in the ArrayList anymore.
  8. livesIcons.remove(livesIcons.size() - 1);

Confirm that your program is working correctly before moving on to the next section.

6.3. Scoring

Keeping track of the score is pretty easy, right? We'll have a score counter, and we can add to it any time we blow up an asteroid. The more asteroids we blow up, the higher the score.

Let's set that up first before figuring out how to display that score for the user.

  1. Along with the other instance variables in AsteroidsGame, declare the variable score.
  2. int score;
  3. Initialize that to 0 in the setup() method:
  4. score = 0;
  5. Every time we have a bullet collide with an asteroid, we'll add to the score.

That feature might be working, but we don't really know at this point. If you want to test it, you can certainly put a print statement in the draw() loop and see the result printed out in the console as the program runs.

println(score);

We want to print it out on the game screen however. Let's learn how to put text on the screen.

  1. In the AsteroidsGame tab, let's set up the size of the text that we'll be printing with:
  2. textSize(32)
  3. Then, wherever we want to print something, you indicate the text to print, along with an x, y position for the text. These values worked well on my screen.
  4. text("Score: " + score, 10, 40);

6.4. Levels

It's not too difficult to clear the screen and get a maximum score of 10. How do we add levels in the game? And what effect should they have on our gameplay?

  1. In AsteroidsGame, declare and initialize a level variable.
  2. We've been keeping track of the number of asteroids in our game using the ArrayList asteroids. How will we know when we should increment the level variable. How will an increasing level make the game harder?
  3. When to level up?

    I decided to make increasing levels of the game harder by a) ramping up the velocity of the asteroids when they're created for each new level, and b) adding another asteroid for every level completed. Fun!

    In the section of the draw() function where you are checking to see if a missile has hit an asteroid:

    // Check for collisions while we're at it! for (int j = asteroids.size() - 1; j >= 0; j--) if (dist(m.getX(), m.getY(), asteroids.get(j).getX(), asteroids.get(j).getY()) < 40) { asteroids.remove(j); missiles.remove(i); score++; if (asteroids.size() == 0) // if we've completed the level { level++; // increment level // put more asteroids in, and make them move faster! for (int k = 0; k < 10 + level; k++) { asteroids.add(new Asteroid()); asteroids.get(k).setXspeed(asteroids.get(k).getXspeed() * (level)); } } }

Next...

Part 7 - Additional possibilities