Program Arcade GamesWith Python And Pygame

To move beyond the simplistic shapes offered by drawing circles and
rectangles, our programs need the ability to work with bitmapped
graphics. Bitmapped graphics can be photos or images created and saved
from a drawing program.

But graphics aren't enough. Games need sound too!
This chapter shows how to put graphics and sound in your game.

The programs we've made so far only involve one file. Now that we are
including images and sounds, there are more files that are part of our program.
It is easy to get these files mixed up with other programs we are making.
The way to
keep everything neat and separated out is to put each of these
programs into its own folder.
Before beginning any project like this, click the “new folder” button and
use that new folder as a spot to put all the new files as shown in
Figure 11.1.
Figure 11.1: Creating a new folder

Need to set a background image for your game?
Find an image like Figure 11.2.
If you are looking on-line in a web browser, you can usually right-click on
an image, and save it onto the computer. Save the image to the folder
that we just created for our game.
Figure 11.2: Background Image

Any bitmap images used in a game should already be sized for how it should
appear on the screen. Don't take a 5000x5000 pixel image from a high-resolution camera
and then try to load it into a window only 800x600. Use a graphics program
(even MS Paint will work) and resize/crop the image before using it in your
Python program.

Loading an image is a simple process and involves only one line of code.
There is a lot going on in that one line of code, so the explanation of the line will
be broken into three parts.
The first version of the our load command will load
a file called saturn_family1.jpg. This file must be located
in the same directory that the python program is in, or the computer will
not find it:

Be careful about using copyrighted images.
If you publish a game with images that you don't have the rights to, that's
illegal. If you are creating your own work that you aren't sharing, then
it is ok. If you are doing a class assignment, make sure that you check with
the instructor for his or her rules around it.

For class assignments, I suggest my students add a comment to the program
just before loading the image. List where the image came from as we did in the
example above. (Don't list Google as the image source, that's like listing the
“library” as your reference source. Find the website the image came from.)

That code may load the image, but we have no way to reference
that image and display it! We need a variable
set equal to what the load() command
returns. In the next version of our load command, we create
a new variable named background_image.
See below for version two:

background_image = pygame.image.load("saturn_family1.jpg")

Finally, the image needs to be converted to a format Pygame can more
easily work with. To do that, we append .convert() to the
command to call the convert function. The function .convert() is
a method in the Image class. We'll talk more about classes,
objects, and methods in Chapter 12.

All images should be loaded
using code similar to the line below.
Just change the variable name and file name as
needed.

background_image = pygame.image.load("saturn_family1.jpg").convert()

Loading the image should be done before the main program loop.
While it would be possible to load it in the main program loop, this would cause
the program to fetch the image from the disk twenty or so times per second. This
is completely unnecessary. It is only necessary to do it once at program start-up.

To display the image use the blit command. This “blits” the
image bits to the screen. We've already used this command once before when displaying
text onto a game window back in Chapter 5.

The blit command is a method in the screen variable,
so we need to start our command by screen.blit.
Next, we need to pass the image to blit, and where to blit it.
This command should be done inside the loop
so the image gets drawn each frame. See below:

screen.blit(background_image, [0, 0])

This code blit's the image held in background_image to the screen
starting at (0, 0).

Now we want to load an image and move it around the screen. We will start off
with a simple orange space ship. You can get this and many other great assets
from http://kenney.nl/.
See Figure 11.3.
The image for the ship can be
downloaded from the book's website, or you can find a .gif or .png
that you like with a white or black background. Don't use a .jpg.
Figure 11.3: Player image

To load the image we need the same type of command that we used with the background
image. In this case, I'm assuming the file is saved as player.png.

player_image = pygame.image.load("player.png").convert()

Inside the main program loop, the mouse coordinates are retrieved, and passed to
another blit function as the coordinates to draw the image:

# Get the current mouse position. This returns the position
# as a list of two numbers.
player_position = pygame.mouse.get_pos()
x = player_position[0]
y = player_position[1]
# Copy image to screen:
screen.blit(player_image, [x, y])

This demonstrates a problem. The image is a space ship with a solid black
background. So when the
image is drawn the program shows Figure 11.4.

We only want the space ship, not a rectangular background! But all images we can load
are rectangles, so how do we show only the part of the image we want?
The way to get
around this is to tell the program to make one color “transparent” and not display.
This can be done immediately after loading. The following makes the color black
(assuming BLACK is already defined as a variable) transparent:

player_image.set_colorkey(BLACK)

This will work for most files ending in .gif and .png. This does not work well for most
.jpg files. The jpeg image format is great for holding photographs, but it does subtly
change the image as part of the algorithm that makes the image smaller.
Images in .gif and .png are also compressed, but the algorithms used in those
formats do not change the image. The format .bmp isn't compressed at all, and
results in huge files.
Because the .jpg format changes the format, this means that not
all of the background color will be the exactly the same. In
Figure 11.5 the space ship has been saved
as a jpeg with a white background. The white around the ship is not exactly
(255, 255, 255), but just really close.
Figure 11.5: JPEG Compression Artifacts

If you are picking out an image that will be transparent, choose a .gif or .png.
These are the best formats for graphic art type of images. Photos should be .jpg.
Keep in mind it is not possible to change a .jpg to another format just by
renaming the file extension to .png. It is still a .jpg even if you call it
something different. It requires conversion in a graphics program to change it
to a different format. But once in a .jpg format, it has been altered and converting
it to a .png won't fix those alterations.

Like images, sounds must be loaded before they are used. This should be done once
sometime before the main program loop. The following command loads a sound file and
creates a variable named click_sound to reference it:

click_sound = pygame.mixer.Sound("laser5.ogg")

We can play the sound by using the following command:

click_sound.play()

But where do we put this command? If we put it in the main program loop it will play
it twenty times or so per second. Really annoying. We need a “trigger.” Some action
occurs, then we play the sound. For example this sound can be played when the user
hits the mouse button with the following code:

Uncompressed sound files usually end in .wav. These files
are larger than other formats because no algorithm has been run on them to make them
smaller. There is also the ever popular .mp3 format, although that format
has patents that can make it undesirable for certain applications. Another format
that is free to use is the OGG Vorbis format that ends in .ogg.

Pygame does not play all .wav files that can be found on the Internet.
If you have a file that isn't working, you can try using the program
Audacity to convert it to an ogg-vorbis
type of sound file that ends in .ogg. This file format is small and reliable for
use with pygame.

Please note that you can't redistribute copyrighted music with your program.
Even if you make a video of your program with copyrighted music in the background
YouTube and similar video sights will flag you for copyright violation.