Charlotte waved goodbye to her mother as she started off on the trail heading north toward the forest. The sun’s rays warmed her back as she walked, with only the occasional birdsong cutting through the tranquility of the day.
After what seemed like no time at all, Charlotte found herself walking between the trees, their leaves and branches forming a shaded canopy above her head. She had arrived at a place that she knew well and which would give her an unobscured view of a clearing directly ahead.
Charlotte unpacked her Canon SLR and waited patiently.
In the last chapter, we set up the game environment and initialized the variables (including the animals dictionary variable which stores data about each of Snapper’s animals). We also displayed the screen background.
- 4.
Draw and move the camera.
- 5.
Show an animal.
- 6.
Hide an animal.
Step 4: Draw and move the camera
The mouse pointer
Line 118 gets the current mouse location using the Pygame mouse.get_pos() function . We store the mouse position in the variable mouse_pos.
The mouse position is stored as two values, one for the x coordinate of the mouse and the other for the y coordinate. To access the x coordinate, we use mouse_pos[0], and to access the y coordinate, we use mouse_pos[1].
We set the center of the camera to the x and y coordinates of the mouse in lines 121 and 122.
Lines 131–134 draw either the normal camera image or the flash camera image. The if statement at line 131 works out whether snap_visible or miss_visible is True. We will make use of these variables later in the code, but for now we can see from looking back at lines 64 and 65, they are both initialized to False and so the camera_image will be displayed by line 134.
Lines 124 and 125 get the camera width and height and store each in a variable.
Lines 128 and 129 prevent the camera from going off the left edge of the screen, while lines 130 and 131 prevent it from going off the right edge of the screen.
Lines 133 and 134 prevent the camera from moving off the top of the screen, while lines 135 and 136 stop it from going below the scoreboard which will appear at the bottom of the screen.
Key learning
pygame.mouse.get_pos() can be used to get the coordinates of the mouse pointer.
Step 5: Show an animal
Using the dictionary
Remember that the data for all 23 animals is held in a fairly large dictionary called animals .
Add the two new lines of code shown in Figure 7-4 at lines 98 and 99.
Line 98 makes use of Python’s random.choice function which picks an item from a list at random. Our code picks a random animal from the animals dictionary.
In fact, random.choice actually gets one of the random animal keys, for example, animal_14 or animal_21. What we really want is the animals dictionary represented by that key. Line 99 initializes the animal variable with the dictionary represented by the random key.
The background
The animal
The foreground overlay
Using the foreground overlay in this way, we can partially hide our animals behind trees, bushes, or even hills.
Line 143 uses a Boolean variable called animal_visible which was initialized to True at the start of the program. Later in the program we will set it to False to hide the animal, but for now animal_visible is True. When set to True, the code between lines 145 and 156 will run, and the correct animal image will be displayed.
Lines 145 and 146 get the values of the animal’s x and y coordinates from the animals dictionary. To get a dictionary item from a dictionary, we use the dictionary’s key. So
animal.get('x_loc'))
Lines 149–156 work out the type of animal and then display its image at coordinates [animal_x,animal_y]. Again, notice the use of the dictionary key to get the animal type:
animal.get('type')
Now when you run the program, a random animal should be displayed. Quit the game, and then run it again. A different animal should be displayed in a new location.
Key learning
Use random.choice to randomly select an item from a list.
To get a value from a dictionary, use dictionary_name.get('key_name').
Step 6: Hide an animal
Now that we have a random animal on screen, we want it to remain visible for a short time and then disappear. If the animal didn’t disappear it would make it too easy to take a photograph and the game would become boring.
Setting a timer
If we look again at the animals dictionary, we will see that each animal has a key 'time '. The value represented by the key 'time' is the length of time that the animal will remain on screen.
Before we can hide an animal, we need to first get the time value by using the 'time' key.
Line 100 assigns the dictionary value of the animal ‘time’ to the animal_timer.
Line 142 checks the animal_visible Boolean variable, and if it is True (the animal is currently on screen) we subtract 1 from the value of animal_timer at line 143. In Python, we subtract a value from a variable using -= (also note that we can add a value onto a variable using +=).
Line 146 checks to see if animal_timer has reached 0. We have already learned that we use == in Python to check if two values are equal.
If the animal_timer equals zero, then line 147 initializes a new variable called no_animal_timer. no_animal_timer is used in a similar way to animal_timer, but it counts down the time until the next animal is displayed.
We set no_animal_timer to a random value so that the length of time between one animal hiding and the next animal appearing is always different. Python’s random.randint() function generates a random integer. In this case, we stipulate that the random number should be between 30 and 120.
Finally at line 148, we set the animal_visible Boolean to False. Recall that we only display an animal if animal_visible is True. By setting the value of this variable to False, no animal will be displayed.
In simple terms, it means that the while True loop will execute 60 times every second. So if we look back at our dictionary, we see that the time value for animal_1 (a rabbit) is 60. That means it will be displayed on screen for exactly one second. By comparison, animal_23 (a deer) has the time value set to 90, so this animal will stay on screen for 1.5 seconds.
(Cheat hint: If you want to make the game easier, increase these time values.)
Rectangles
The code in Figure 7-7 has some additional lines which we have not explained yet.
Lines 150–160 are used to work out the size and location of the animal image currently on screen. Each image is actually a rectangle. We won’t go into this code in much detail at the moment other than to say we use it to work out if the camera is on top of the animal when the player takes a photograph.
Key learning
We can use -= to subtract a value from a variable, for example, animal_timer -= 1 will subtract 1 from the variable animal_timer.
Use random.randint() to generate a random number, for example, random.randint(1, 10) will generate a random number between 1 and 10.
Show another animal
Line 163 checks to see if the animal_visible is False; in other words, there is no animal currently being shown.
If that’s the case, we subtract 1 from the no_animal_timer at line 164.
Line 166 checks to see if the no_animal_timer has reached 0.
Line 167 then checks to see if we have any lives left.
If the timer has reached 0, and we still have lives left, we need to generate a new random animal. For now, we will use exactly the same code as we did when generating a random animal earlier in the program at lines 168 and 169.
Line 170 sets up the new animal_timer (we have seen this before at the start of the program).
At line 171, we set the animal_visible variable to True so that the animal will be shown.
Lastly, we set the values of the two Booleans snap_visible and miss_visible to False. We will see shortly how we make use of them.
Building a function
Notice how we generated a random animal at two different places in the program, once at the start of the code and then again when we wanted to get a new animal to show. Copying code in this way is not considered good practice. What happens, for example, if we change the code that generates a random animal? We would have to remember to change the code in both places.
Instead, it is better practice to build a single block of code to do this. In programming, it is common to break a program down into smaller blocks of code that carry out a specific task. In Python, these code blocks are called functions.
A function is a block of code that carries out a specific job. It may optionally return a value back into the main program when it has finished.
Enter the function code as shown in Figure 7-9 near the foot of the program. Notice the use of two blank lines above and below the function.
Next, we need to go back to our main program and change the code so that it makes use of this function instead.
- 1.
The program reaches line 98:
animal = get_random_animal(animals).
- 2.
Python doesn’t know what get_random_animals is, so it looks to see if there is a function by that name. Of course, there is:
def get_random_animal(animals):
- 3.
Did you notice in the main program the word animals is between the brackets? This is known as a parameter , and we are going to pass this parameter into the function. Remember that animals is our dictionary which stores data about all of the animals in Snapper.
- 4.
Look again at the get_random_animal function. It also has the word animals between the brackets. The animals dictionary will be passed from the main program into the function where it will also be known as animals. We can now access the animals dictionary in our function.
- 5.
The two lines of the function are almost exactly the same as the two lines of code that we replaced in the main program. However, there is one key difference. At the end of the function, it returns the random animal. But what does that mean? If we look back up to line 98, we see that
animal = get_random_animal(animals).
The function therefore returns the random animal, and it is assigned to the variable animal in the main program.
When our main program code runs a function, we say that it calls the function.
Don’t worry if you find the concept of functions a bit tricky to understand – we will be revisiting functions again later in the book.
Key learning
Functions are blocks of code that carry out a specific task. Parameters can be passed into a function, and a result can be returned out of the function back to the main program.
We can see that Snapper is beginning to take shape. In the next chapter, we will see how we can tie all the parts of the game together by writing the code which will take a photograph.