Greenfoot Avoider Game Tutorial - Part III

by Michael L. Haungs

Part III: Enhancing Playability

We need a score!

Our game is becoming more interesting, however, we need a way to judge how well we are doing in the game. There are many ways to judge game performance (e.g. levels completed, time, progression) but the most common method is to assign the player a "score". We are going to add a scoring system to the game that rewards players for the number of enemies they avoid.

The code...

We are going to add a scoreboard to display the score to the player. Obviously, a "scoreboard" is not a World, therefore, it must be an Actor. Create a new subclass of Actor and name it "ScoreBoard". Do not associate an image with this class. Edit the code for ScoreBoard so that is looks like this:

Scoreboard code

The Explanation...

OK, let's tackle the ScoreBoard code one method at a time.

act()
Our scoreboard does not have any independent action that it must perform. Changes in score are done via the addScore() method, thus, this method is empty.
getScore()
Later in this tutorial, we will create levels for the game. The levels will change based on the current score. This method allows us to access the current score stored in the ScoreBoard.
addScore()
Whenever we detect we have avoided an enemy, we will call this function to add points to our score.
ScoreBoard()
This is our constructor method. Remember my big long explanation of constructor methods from Part II? This is where we put all of our initialization code. Our score is going to consist of two parts. First, we will draw a box to hold the score in and, second, we will draw the score text on top of this box. While the score will constantly change, the background box only needs to be created once (and that's why it is in the constructor function). I use the GreenfootImage class to construct and draw the background box. Read the documentation to fully understand the GreenfootImage methods I used.
update()
This function does the real work of displaying our score. Notice the use of this method in the other methods in the class. In Greenfoot, text is viewed as an "image". So, we also use the class GreenfootImage to create text. This method creates a score by creating a new background image and drawing an image that contains the score text into it. Again, read the documentation for GreenfootImage to understand the methods I used.

 

Did you really get this far without compiling and running? Shame on you!! You should be doing this every time you write 3-5 lines of code!

 

Where's the score?

We want the score to appear immediately in the game. In tutorial 4 on the Greenfoot site, you were introduced to "Saving the World" to have the World class automatically place Actors in your world. I'm going to describe how to place Actors in your world manually. First, in your AvoiderWorld() constructor function, you need to add a function call at the end of that function. The function call you need to add is "prepare();". Next, we need to create a variable at the top of our class (outside any method) to hold our ScoreBoard. Add "private ScoreBoard scoreboard;" above the constructor function. Last, you need to add this function to your AvoiderWorld class:

Prepare function code

The prepare() method contains code you have seen before and should make perfect sense to you. It does, doesn't it?

(compile, run, test)

I'm the worst! My score is always 0!

We need to do just one more thing. We need to call addScore() on our scoreboard to increase our score over time. One place we could do this is where we create the enemies in AvoiderWorld. The thinking is that you get some points for every enemy created because you will ultimately have to avoid it. Here's how you should change the act() method in AvoiderWorld:

Act method with adding points

Try it out? Are you getting an increased score?

This is tricky! Can I get more instruction?

Yes! The Greenfoot documentation has a tutorial. Check it out:

  • http://www.greenfoot.org/doc/howto-1

 

Adding Levels

Our game isn't very challenging at this point. One thing we could do is have the game become more challenging over time. In this part of the tutorial we are going to add the notion of "levels" to our Avoider Game. I'm going to increase the challenge in the game by periodically increasing the rate at which enemies spawn and the speed at which they travel. In AvoiderWorld, add two variables "enemySpawnRate" and "enemySpeed" we will use to increase difficulty. The top of your AvoiderWorld class should look like this:

The variables to add to AvoiderWorld

Next, we need to add a function that increases the difficulty of the game based on the player's score. To do this, we need to add the following two methods to AvoiderWorld:

Add increase level method to Avoider World

As evident from the code, we increase both enemySpawnRate and enemySpeed as the player's score increases. The last thing we need to do is use the enemySpawnRate and enemySpeed variables in the creation of enemies and to call increaseLevel() from the act() method in AvoiderWorld. Here is the new act() method of AvoiderWorld:

The act method with increase level code added.

Compile and Run!!!!

 

 

Oops...

 

 

We have an error. In the act() method above, we use the line "e.setSpeed(enemySpeed);" to change the speed of the enemy, however, we never have implemented that method in the Enemy class. I'm not going to show you how to implement that. You can do it! Your awesome, capable, and talented! Add that method and compile and run. Hopefully, all goes well....

Your Assignment

Implement the following:

  1. Once the player's score is above 900, add a new enemy that spawns in addition to the enemies we have now. The new enemy should visually be very distinct from our existing enemies. (optional) If you are feeling up to it, have the new enemy move differently from the existing enemies too.
  2. Periodically, spawn a power-up that gives our hero a special ability. For example, the power-up could make our hero temporarily invincible, allow our hero to kill three enemies, or shrink the size of the avatar making it easier to avoid enemies.
  3. Display the player's final score on the Game Over screen.

Next...

Congratulations! You did it!