Charlotte lay perfectly still, her breathing almost inaudible. All that she could hear was the sound of her own heart thumping in her chest. Her eyes scanned between the trees. Over there. Was that something moving, or was it her imagination? A cracking twig broke the silence.
Charlotte’s gaze focused. There was something. A mere silhouette, she could see a head maybe, but what was it? Too big for a rabbit. She could almost make it out now, copper-brown fur the color of scorched earth, a lighter tail only just visible.
A deer stood less than 30 meters in front of Charlotte, staring right back at her.
With the most subtle of movements, she picked up her camera and zoomed in.
So far, our game has animals appearing and then hiding, and we can control the location of the camera by moving the mouse. In order for Snapper to become a game, we need to be able to take photographs.
- 7.
Taking a photograph
- 8.
Game over
- 9.
Scoreboard
Step 7: Take a photograph
Add the code in Figure 8-1 at line 114. With this code, we check to see if the mouse button is clicked and if so set the variable mouse_button_pressed to True. Otherwise, it will remain False.
Add the code from Figure 8-2 at line 145 to calculate the viewfinder rectangle.
Rectangles collide
The if statement at line 178 is relatively straightforward – it is testing to see if a photo has been taken. A photo will have been taken if mouse_button_pressed has been set to True. Remember we set mouse_button_pressed to True when Pygame detects a MOUSEBUTTONDOWN event.
The if statement at line 179 checks three variables. The first two, snap_visible and miss_visible, will be covered later. The third check is to find out whether lives > 0. When the game is over, lives will be 0, so here we are checking that the game is not over.
The if statement on line 189 uses a really important Pygame function called colliderect. colliderect is important when writing games because it takes two rectangles and checks if they have collided with each other. We can use colliderect in games to test if a missile has hit a spaceship, if a racing car has driven over a patch of oil, or, in the case of Snapper, if the animal is in the camera viewfinder.
colliderect takes the format rectangle_1.collide_rect(rectangle_2).
It will return True if the rectangles have collided and False if they have not collided.
The if statement on line 190 tests to see if the animal is visible. If the player takes a photo when there is no animal, then it will count as a failed photo.
Snapped it!
The mouse button is pressed.
It is not game over.
The animal is in the camera’s viewfinder.
The animal is actually visible.
Line 191 calculates how much time was left on the timer, multiplies that by the points value for the animal, and adds the result onto the game score.
Line 192 sets snap_visible to True. When snap_visible is True, a green tick will display in the camera viewfinder, and we can’t take another photo.
- Line 193 plays an audio file – the camera shutter effect.
Run the program and try to take a picture. If you are successful, you will hear the camera shutter sound effect being played, and the camera screen will go black. If you are unsuccessful, well, nothing happens, not yet anyway. Let’s fix that.
Oops, missed!
Line 196 sets miss_visible to True. miss_visible is a Boolean variable very similar to snap_visible, but it will be used to show a red cross instead of a green tick.
Line 197 subtracts one from the number of lives that the player has.
Line 198 plays a buzzer sound effect to indicate that the photo was unsuccessful.
This else statement will be reached if the viewfinder rectangle did not collide with the animal rectangle. In other words, the player missed the animal when they took their photograph. If this happens, lines 201–203 will be run, which as we can see do exactly the same thing as lines 196–198.
Whether the photo was successful or not, we run lines 206–208 to hide the animal, cancel the animal timer, and start a no animal timer.
Hit or miss?
Lines 238–240 work out the dimensions of the rectangle which will hold the snap_image or the miss_image. The tick/cross image will be positioned in the middle of the camera viewfinder.
Lines 242–246 will display either the snap_image (green tick) if snap_visible is True or the miss_image (red cross) if miss_visible is True. Of course, if neither is True, then neither will be displayed.
Run the game again to see this code in action.
Key learning
Pygame has an event MOUSEBUTTONDOWN which is set when the mouse button is clicked.
The Pygame function colliderect is used to determine if two rectangles have collided.
Step 8: Game over
Line 120 gets details of any key presses from the Pygame get_pressed() function and stores them in the variable key_pressed,
- Line 121 checks for two things:
To see if the key pressed was RETURN
To see if the number of lives remaining equals zero (in other words, is it game over)
Lines 122–123 check if the score has beaten the current high score and, if so, set the high score to the game score. We saw this code used in Forest Bomber.
Lines 125–126 reset the number of lives and the score.
Line 128 uses our get_random_animal function to get a new random animal.
Lines 129–130 set up the animal_timer and the no_animal_timer.
Finally, lines 132–135 ensure that the animal will be visible and the snap_image and miss_image are both hidden.
And that’s it. A new game is set up ready to go. Run the code to test it.
The only thing that’s missing is a scoreboard.
Step 9: Scoreboard
In Forest Bomber, we saw how to write code to display a scoreboard. We will use a similar process in Snapper, but this time the scoreboard will be displayed at the bottom of the screen.
display_scoreboard_data to display the text on the scoreboard
display_game_over to display the game over message at the end of the game
Next, add the display_game_over function at line 291 as shown in Figure 8-9. Note that there are two blank lines separating each function. While the number of blank lines does not affect the program, it makes the program that little easier to read.
We won’t look at the code held in these functions in any detail, other than to say that they use math to align and display any text and rectangular boxes on the screen.
Some text which will be stored in the parameter scoreboard_text.
The alignment setting for the text, which will be stored in the parameter alignment. The alignment is a string which can be either ‘Left’ or ‘Centre’, and this function will align the text accordingly.
A final block of code is needed to make use of these functions and complete the Snapper game.
Notice that we are calling our display_scoreboard_data function at line 267 and again at line 270. We call the display_game_over function at line 279.
Well done! You have now programmed two games. Don’t spend too long playing Snapper though – I hear that planet earth is about be hit by an alien invasion…