Programming Basics

  Home arrow Programming Basics arrow Python in Game Development
PROGRAMMING BASICS

Python in Game Development
By: Apress Publishing
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating:  stars stars stars stars stars / 0
    2011-08-04

    Table of Contents:
  • Python in Game Development
  • Using the Standard Library

  •  
     

    SEARCH CODEWALKERS

    TOOLS YOU CAN USE

    advertisement

    Python in Game Development


    (Page 1 of 2 )

    In this fifth part of a six-part series on the Python programming language, we'll go hands-on by starting to create a game application to teach you some important concepts. This article is excerpted from chapter two of the book Beginning Game Development with Python and Pygame: From Novice to Professional, written by Will McGugan (Apress; ISBN: 9781590598726).

    Python in Practice

    The game we are going to create is more of a simulation than a game, but it should be enough to introduce a few important game concepts. We will create a number of tanks and let them take shots at each other. The winner is simply the last tank left in the game. Listing 2-7 shows the code that completes the tank game.

    Listing 2-7. tankgame.py

    from tank import Tank

    tanks = { "a":Tank("Alice"), "b":Tank("Bob"), "c":Tank("Carol") }
    alive_tanks = len(tanks)

    while alive_tanks > 1:

    print
    for tank_name in sorted( tanks.keys() ):
    print tank_name, tanks[tank_name]

    first = raw_input("Who fires? ").lower()
    second = raw_input("Who at? " ).lower()

    try:
    first_tank = tanks[first]
    second_tank = tanks[second]
    except KeyError, name:
    print "No such tank!", name
    continue

    if not first_tank.alive or not second_tank.alive:
    print "One of those tanks is dead!"
    continue

    print
    print "*" * 30

    first_tank.fire_at(second_tank)
    if not second_tank.alive:
    alive_tanks -= 1

    print "*" * 30

    for tank in tanks.values():
    if tank.alive:
    print tank.name, "is the winner!"
    break

    When you see any piece of code for the first time (in any language), it can be a little intimidating. But once you break it down you should find that it consists of familiar things. So let’s dissect Listing 2-7 like a trained chef preparing fugu!

    The first thingtankgame.pyneeds to do is import our tank module, which contains theTankclass. When a new script runs, it only has access to the built-in classes, such as strings and lists. If you want to use another class that isn’t defined directly, you first have to import it from another Python file. The linefrom tank import Tanktells Python to look for the module calledtank(.pyis assumed) and read in theTank class. An alternative would be to do a simpleimport tank, which would let us access everything insidetank.py.


    Note When you dofrom tank import Tank, it imports theTank class (capital T) to the current namespace—which means you can now useTankas if you had just cut and pasted it into your script. However, if you just doimport tank, you have imported thetanknamespace, which means you would have to refer to theTank class astank.Tank, as inmy_tank = tank.Tank("Bob"). See the section “Introducing import” later in this chapter for more details on theimportstatement.


    Next we create a dictionary calledtanks, which will be used to store all our tank objects. We will work with three, but feel free to add more tanks if you like.

    tanks = { "a":Tank("Alice"), "b":Tank("Bob"), "c":Tank("Carol") }
    alive_tanks = len(tanks)

    The three tanks have the strings"a","b", and"c"as keys, so we can look them up easily. Once we create our tanks, we store the number of tanks inalive_tanksso we can keep count of tanks still in the game:

    while alive_tanks > 1:

    This starts off a while loop that keeps going while there is more than one surviving tank. Games always have a big loop at their core. For a visual game the main loop runs once per frame to update and display visuals, but here the loop represents a single round in the simulation.

    Inside the while loop we first print a blank line to make the text for each round a little easier to separate. Then we have another loop that displays a little information on each of the tanks:

    print
    for tank_name in sorted( tanks.keys() ):
    print tank_name, tanks[tank_name]

    Thekeysmethod of dictionaries returns a list of the keys that it contains, but because of the nature of dictionaries the keys won’t necessarily be in the order that they were added. So when we get the list of keys fortankswe immediately pass it tosorted, which is a built-in function that returns a sorted copy of a list.

    Theprintstatement inside the for loop looks up the key in thetanksdictionary and prints the tank object it finds. Remember, printing an object calls its__str__function to get some useful information.

    Next we ask the user for two tanks: the tank that fires (first) and the tank that it hits (second):

    first = raw_input("Who fires? ").lower()
    second = raw_input("Who at? " ).lower()

    The built-in functionraw_inputdisplays a prompt and waits until the user has entered some text, which it returns as a string. In the preceding code we call thelowermethod of the returned string to convert it to lowercase because we need a lowercase string to look up the appropriate tank, but we don’t mind if the user enters a name using uppercase letters.

    With the two tank keys in hand, we can use them to look up the actual tank object. This is simple enough: we can just dotanks[first]to retrieve the tank:

    try:
    first_tank = tanks[first]
    second_tank = tanks[second]
    except KeyError, name:
    print "No such tank!", name
    continue

    But because the user could type anything at the prompt, we need some way of handling a situation where the user makes an error or deliberately tries to break our game!

    Whenever Python is unable to do something it is asked to do, it will throw an exception. If you don’t do anything to handle these exceptions, the Python script will exit—which would be disastrous in a real game. Fortunately it is possible to predict potential exceptions and handle them if they occur. If eitherfirstorsecondis not a key in thetanksdictionary, then Python will throw aKeyErrorexception when we try to look either of them up. This won’t make the script exit because we look up the keys inside atry:block, which says to Python that the code block may throw an exception. If aKeyErrordoes occur, Python jumps to the code underexcept KeyError:(which is ignored if no exception occurs).

    Inside ourKeyError exception handler we first display a brief message to inform the user that they did something wrong, and then move on to acontinuestatement, which tells Python to ignore the rest of the code in this loop and jump back to the top of the innermost loop.

    if not first_tank.alive or not second_tank.alive:
    print "One of those tanks is dead!"
    continue

    This piece of code handles the situation if one or both of the tanks is dead—since there is no point in firing on a dead tank, and tanks that are dead can’t fire anyway! It simply displays a message and does anothercontinue.

    If we have managed to get to this point in the code, we have two valid tank objects:first_tankandsecond_tank:

    first_tank.fire_at(second_tank)
    if not second_tank.alive:
    alive_tanks -= 1

    The first tank does the firing, so we call itsfire_atmethod and pass in the second tank as the enemy. If the second tank is killed by the first (armorreaches 0), itsaliveproperty will be set toFalse. When this happens, thealive_tankscount is reduced by 1.

    Eventually, after a few rounds of the game the value ofalive_tankswill reach 1. And when that happens, the main game loop will end, as it only loops whenalive_tanksis greater than 1.

    The purpose of the last section of code is to display which tank won the game:

    for tank in tanks.values():
    if tank.alive:
    print tank.name, "is the winner!"
    break

    It is another loop that goes through each value intanks.values(), which is the complement tokeys()—it gives us a list of all our tank objects. We know that there is only one tank that hasalive set toTrue, so we test it with a simpleifstatement. Once we find that last remaining tank, we print a little message and then execute thebreak statement. Thebreakstatement is the partner tocontinue, but rather than jumping to the beginning of the loop, it jumps to the end and stops looping.

    So that’s our little game. Now I’d be the first to admit that it is not the most exciting of games. It’s no Quake beater, but even Quake will do similar things. All 3D shooters must keep track of health/armor and ammunition, as well as who is still alive. By the end of this book, though, our game objects will be rendered in stunning 3D rather than a line of text. The following is the output fromtankgame.py:

    --------------------------------------------
    a Alice (60 armor, 5 shells)
    b Bob (60 armor, 5 shells)
    c Carol (60 armor, 5 shells)
    Who fires? a
    Who at? b

    ******************************
    Alice fires on Bob
    Bob is hit!
    ******************************

    a Alice (60 armor, 4 shells)
    b Bob (40 armor, 5 shells)
    c Carol (60 armor, 5 shells)
    Who fires?
    --------------------------------------------

    More Programming Basics Articles
    More By Apress Publishing

    blog comments powered by Disqus

    PROGRAMMING BASICS ARTICLES

    - The Transliteration Operator in Perl
    - Perl String Processing Functions
    - Perl String Processing
    - Control Flow Constructs: Loops Conclusion
    - Loop Control Constructs
    - Control Flow Constructs: the For and Foreach...
    - Loops and Control Flow Constructs
    - Expression Modifiers for Perl Control Flow C...
    - Logical Operators and Control Flow Constructs
    - Comparing Strings with Control Flow Construc...
    - Perl Operators and Control Flow Constructs
    - Control Flow Constructs
    - More Time Manipulation with PHP
    - Validating and Manipulating Dates with PHP
    - Using the Date Constructor in PHP

    Developer Shed Affiliates

     



    © 2003-2013 by Developer Shed. All rights reserved. DS Cluster - Follow our Sitemap