Lab 9: File I/O, sound, randomization

This final lab involves some additional changes to the code from last week's lab exercise. This time, you'll be adding the ability to read map information from a text file, randomly select from a set of available maps, and add music and sound effects (along with a flag that allows you to turn them off in the labs, where the pygame sound routines don't work).

The initial setup involves copying python and image from the instructor's account to your own, and making each of the programs executable.

Initial setup

First, as always, move into your games directory, create a directory for this lab, and move into that. E.g.

   cd games  
   mkdir lab9
   cd lab9
Next, copy across a whack of files for this week's lab: backdrop.gif, finish.gif, game9.py, ghost1.gif, ghost2.gif, grass.gif, lake.gif, map0.txt, map1.txt, map2.txt, map3.txt, map4.txt, map5.txt, map6.txt, music.mid, wall.gif, win.wav.

Run the chmod command to make any python scripts executable:
chmod u+x *.py
Open the program with your editor:
gedit game9.py &
And run the program to test it out:
./game9.py

This completes the setup, you can now proceed to the actual lab exercises below


Part 1: reading maps from a text file

The objective here is to have a bunch of text files that each contain a description of a different map, and when we want to play the game we get it to load one of the maps and create the appropriate display.

To read the map in, our program will need to know the format we decide on for the text file.

In this example, I'll have the file start with three numbers: the size of the tiles in pixels, the number of map rows, and the number of map columns.

After that, we'll have the actual ASCII map. Here using ~ to represent water, * to represent walls, f to represent the finish flag, and blank spaces to represent grass:

To read data from a file we go through several steps:

The syntax for doing this in any given programming language is sometimes a trifle odd, but here's an example of the Python approach:

Now, suppose something goes wrong - the file contains bad data, or the file is missing, or is too big, or a variety of other things that could go wrong. Maybe we should introduce a fallback routine, that can build a default map if the attempt to read a map goes awry.

This looks an awful lot like our original definition of the various global map variables, just stuck in a function this time.

Of course, somewhere we need to try to read in the map, see if it worked, and use the default routine otherwise.

The logical place for this is in the setup routine, before we start our display (since we're calculating the size of the display based on the size of the tiles and the number of map rows and columns).

Let's throw in one more test, checking to see if the map we've created will actually fit on the screen the player is playing the game on.

This can be done using pygame's display.list_modes() routine:


Part 2: randomly selecting which map to read

If we know we have a variety of map files to choose from, we can add a bit of unpredictability by having the game randomly choose which map to load at startup.

This would happen in the setup routine, just before calling readMap


Part 3: adding music and sound effects

We'll add some music and sound effects, but we'll also add a global flag that lets us turn them off. This is important, since they must be turned off when running them in the lab.

In the main routine, sometime before the beginning of the keepPlaying loop, we'll start the background music playing:

In the routine that checks for a win, if someone has won we'll stop the music and play a victory sound:


Complete version

Here's the full beast, with all the parts in the right places: