© Mark Cunningham 2020
M. CunninghamGame Programming with Code Angelhttps://doi.org/10.1007/978-1-4842-5305-2_7

7. Snapper part 2: Say cheese

Mark Cunningham1 
(1)
Edinburgh, Scotland
 

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.

Our next steps are the following:
  1. 4.

    Draw and move the camera.

     
  2. 5.

    Show an animal.

     
  3. 6.

    Hide an animal.

     

Step 4: Draw and move the camera

The mouse pointer

The camera’s movement is going to be controlled by the mouse. We can do this quite easily. Insert the code shown in Figure 7-1 at line 117.
../images/482396_1_En_7_Chapter/482396_1_En_7_Fig1_HTML.jpg
Figure 7-1

Snapper code listing 7

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.

Next, we need to actually draw (blit) the camera onto the game background. Enter code listing 8 (Figure 7-2) at line 130 of the program.
../images/482396_1_En_7_Chapter/482396_1_En_7_Fig2_HTML.jpg
Figure 7-2

Snapper code listing 8

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.

Run the program and move the mouse – the camera should move around the screen. That’s pretty neat, but notice that the camera disappears off the edge of the screen. We don’t want that to happen, so let’s fix it. Add the code from Figure 7-3 at line 124.
../images/482396_1_En_7_Chapter/482396_1_En_7_Fig3_HTML.jpg
Figure 7-3

Snapper code listing 9

What’s going on here?
  • 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 .

Our next challenge is to display one of the 23 animals on screen – but which one should we show? We want our program to choose one of the animals at random. Making random choices is one of the core fundamentals of game programming. After all, who wants to play a game that does exactly the same thing every time?
../images/482396_1_En_7_Chapter/482396_1_En_7_Fig4_HTML.jpg
Figure 7-4

Snapper code listing 10

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.

For example, let’s say that line 98 randomly selected the key animal_7. Line 99 stores the dictionary representing animal_7 in the animal variable, so animal would look like this:
{'type': 'rabbit', 'x_loc': 265, 'y_loc': 318, 'time': 60, 'points': 10}
Now that we have a random animals dictionary, let’s use it to display the animal on screen. Remember that 'type' stores the type of animal to be displayed, while 'x_loc' and 'y_loc' are the animal’s coordinates.
../images/482396_1_En_7_Chapter/482396_1_En_7_Fig5_HTML.jpg
Figure 7-5

Snapper code listing 11

Add the block of code shown in Figure 7-5 at line 143 of the program. Notice that we are drawing the animal after the background but before the foreground overlay. With blit, each image is drawn on top of any previously drawn images. In Snapper we draw the screen elements in the following order:
  • 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.

Examining code listing 11 we can see that:
  • 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'))
gets the x_loc from the animals dictionary.
  • 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.

Add line 100 as shown in Figure 7-6.
../images/482396_1_En_7_Chapter/482396_1_En_7_Fig6_HTML.jpg
Figure 7-6

Snapper code listing 12

Line 100 assigns the dictionary value of the animal ‘time’ to the animal_timer.

Next we have to count down the timer and hide the animal when it reaches 0. Add code listing 13 as shown in Figure 7-7.
../images/482396_1_En_7_Chapter/482396_1_En_7_Fig7_HTML.jpg
Figure 7-7

Snapper code listing 13

Lines 142–148 handle our animal timer, but how do they work?
  • 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 +=).

Because the entire game code runs in a while True loop , the program will keep looping, subtracting 1 from animal_timer each time through the loop until the timer hits zero.
  • 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.

You may be wondering what these timer numbers actually equate to in real time. Look to the very bottom of the Snapper code, and you will see the line
clock.tick(60)

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

Next, we need to count down the no_animal_timer and then display another random animal on screen.
../images/482396_1_En_7_Chapter/482396_1_En_7_Fig8_HTML.jpg
Figure 7-8

Snapper code listing 14

Enter the code shown in Figure 7-8 at line 162. Let’s take a look at it:
  • 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.

We will create a function to generate a random animal, and we will call our function get_random_animal . As with naming variables, we can call a function anything we wish, but it is good practice for the name of the function to describe what it does. So get_random_animal does exactly what it says on the tin!
../images/482396_1_En_7_Chapter/482396_1_En_7_Fig9_HTML.jpg
Figure 7-9

Snapper code listing 15

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.

Replace lines 98 and 99 of the program shown in Figure 7-10 with the single line of code shown in Figure 7-11.
../images/482396_1_En_7_Chapter/482396_1_En_7_Fig10_HTML.jpg
Figure 7-10

Code to be replaced

../images/482396_1_En_7_Chapter/482396_1_En_7_Fig11_HTML.jpg
Figure 7-11

Snapper code listing 16

Similarly, replace lines 167 and 168 shown in Figure 7-12 with the single line of code shown in Figure 7-13.
../images/482396_1_En_7_Chapter/482396_1_En_7_Fig12_HTML.jpg
Figure 7-12

Code to be replaced

../images/482396_1_En_7_Chapter/482396_1_En_7_Fig13_HTML.jpg
Figure 7-13

Snapper code listing 17

The code works like this:
  1. 1.

    The program reaches line 98:

    animal = get_random_animal(animals).

     
  2. 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. 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. 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. 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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.227.190.93