Beginning Python Games Development, Second Edition


Чтобы посмотреть этот PDF файл с форматированием и разметкой, скачайте его и откройте на своем компьютере.
Kinsley
McGugan
SECOND
EDITION
US $ 39.99
Shelve in:
Graphics/Game Programming
User level:
BeginningIntermediate
www.apress.com
SOURCE CODE ONLINE
RELATED
BOOKS FOR PROFESSIONALS BY PROFESSIONALS

Beginning Python Games
Development
Beginning Python Games Development, Second Edition
teaches you how to create
compelling games using Python and the PyGame games development library. Written
a comprehensive, practical introduction to games development in Python. You can also
capitalize upon numerous tips and tricks the authors have accumulated over their careers
creating games for some of the worlds largest game developers.
In this update to the first ever book to cover the popular open source PyGame games
creation of a real-world, freely downloadable video game.
�s���(�O�W���T�O���U�S�E���0�Y�'�A�M�E���W�I�T�H���0�Y�T�H�O�N���F�O�R���G�A�M�E���D�E�V�E�L�O�P�M�E�N�T
�s���(�O�W���T�O���C�R�E�A�T�E���V�I�S�U�A�L�S����D�O���E�V�E�N�T���H�A�N�D�L�I�N�G����A�N�D���M�O�R�E
�s���(�O�W���T�O���D�O����$���G�A�M�E���D�E�V�E�L�O�P�M�E�N�T���U�S�I�N�G���0�Y�T�H�O�N
�s���(�O�W���T�O���A�D�D���M�E�D�I�A���E�L�E�M�E�N�T�S
�s�����(�O�W���T�O���C�R�E�A�T�E���V�I�S�U�A�L�L�Y���D�Y�N�A�M�I�C���B�A�C�K�G�R�O�U�N�D�S���B�Y���I�N�T�E�G�R�A�T�I�N�G���S�O�M�E���/�P�E�N�'�,���A�N�D��
more into your Python-based game
�s���(�O�W���T�O���B�U�I�L�D���A���G�A�M�E���P�R�O�J�E�C�T���S�T�E�P���B�Y���S�T�E�P
97
8
1484
20971
4
53999
ISBN 978-1-4842-0971-4























For your convenience Apress has placed some of the front
matter material after the index. Please use the Bookmarks
and Contents at a Glance links to access them.





echnical Reviewer

Introduction

...........................................................................................................
xxi
Chapter 1: Intr
oducing Python

..............................................................................
1
Chapter 2: Exploring Python

................................................................................
19
Chapter 3: Intr
oducing Pygame

...........................................................................
39
Chapter 4: Cr
eating Visuals

.................................................................................
61
ve

..........................................................................
83
Chapter 6: Accepting User Input

........................................................................
103
ake Me to Your Leader

....................................................................
129
ving into the Third Dimension

.....................................................
153
Chapter 9: Exploring the Thir
d Dimension

.........................................................
169
Chapter 10: Making Things Go Boom

................................................................
197
Camera, Action!

..................................................................
219

......................................................
245
Appendix A: Game Object Refer
ence

.................................................................
265
ackaging Your Game

....................................................................
273
Index

.....................................................................................................................
277
xxi
xxii
Chapter 6 tells you all you need to know to interface your game with virtually any gaming device. The
sample code in this chapter will have you moving a character around with the keyboard, mouse, and joystick.
Chapter 7 is a little unusual in that it is more self-contained than the others and doesn’t depend as
much on previous chapters. It covers the subject of artificial intelligence and includes a fully working
simulation of an ant’s nest, but the techniques I explain in this chapter can be used to add seemingly
intelligent characters to any game.
Chapters 8 and 9 are a gentle introduction to working with three-dimensional graphics in Pygame,
which is an essential topic since most games have 3D elements these days—even if they are not full 3D
games. I explain the math in visual terms that make it easier to grasp, and you should find that it is not as an
intimidating a subject as it first appears.
Chapter 10 takes a break from 3D graphics to discuss how to use Pygame to add sound effects and
music, and even includes a fully working jukebox application.
The final two chapters build on Chapters 8 and 9 to advance your knowledge of 3D graphics, and explain
how to take advantage of the dedicated game hardware on your graphics card. By the end of Chapter 11 you
will have enough knowledge to render and manipulate a three-dimensional object on the screen. Chapter 12
explores several techniques you can use to create even more impressive 3D visuals and generate special effects.
In addition to the 12 chapters, there are 2 appendixes: Appendix A is a reference to the Game Objects
library that is used throughout the book, and Appendix B explains how you can package your game and send
it to others.
Prerequisites
To run the code in this book, you will need at least version 3.4 of Python and version 1.7.1 of Pygame,
which you can download from
, respectively. If you want to run the
3D sample code, you will also need PyOpenGL, which you can download from
Note

there may be a later version of Python available. The differences
for multiply, and
for divide. These
symbols are known as
operators
. You will probably use
the most. Here are some examples:
In the real world there is only one kind of number, but computers—and consequently Python—have
several ways of representing numbers. The two most commonly used types of number are the
integer
float
. Integers are whole numbers with no decimal point, whereas floats do have a decimal point and
can store fractional values. Often it is obvious which one you should use—for instance, if your game has the
lives
, you would use an integer to store them because you are not likely to have half a life or
3.673 lives. Float values are more often used for real-world values that need precision—for example, in a
racing game your car may have a speed of 92.4302 miles per hour, which you would store in a float.
So far the numbers you have entered have been integers. To tell Python a number is a float, simply
include a decimal point. For example, 5 and 10 are integers, but 5. and 10.0 are floats.
In addition to the basic math there are a number of other things you can do with numbers. Parentheses
Strings
Another piece of information that Python can store is the
string
. A string is a collection of characters (a
character
So now you have several ways of creating strings, but what can you do with them? Just like numbers, strings
Figure 1-1.
tring indexing
to use
to find the last character in a string:
()'i'Easy enough, I hope you will agree! But Python can make it even easier for us by using
negative
indexing
We can now find the last character with a little less code:
'i'Slicing StringsIn addition to extracting individual characters in a string, you can pick out groups of characters by
slicing
Figure 1-2.
Negative indexing
You will notice that Python doesn’t print anything after the call to
; this is because the
does

Here we have created a tuple with two strings containing the area code and number of our fugu
The final collection type we are going to look at is the
dictionary
. The previous collections we looked at
have all been
sequence
collections, because the values are in a sequence from first to last and you access
them by their position within the list. Dictionaries are
mapping
collections because they map one piece
of information to another. We could use a dictionary to store the prices of our shopping list by mapping
Note

O
n some systems you may find that a tab is automatically inserted on the first line of a block. This
can be convenient if there is a lot of code in a block.
D
E
nter as normal to end the block.

omparison Operators
OperatorDescription
Less than
Less than or equal to
Greater than
Greater than or equal to
Equal to
Not equal to
16
Be careful with your loops! If you use a condition that is always true, such as
, Python will
keep going round the loop forever. If you do end up in this pickle, press Ctrl+C to stop Python in its tracks.
very
programmer has been stuck in an infinite loop at least once!
That’s all it takes! The variable
now holds the sum of every item in our shopping list, and we can
see the grand total is a very reasonable $171. Don’t worry, the sample code in the following chapters will be
much more entertaining than a grocery list!
Summary
We have explored some of the basic Python constructs in this first chapter, most of which you will use
regularly when writing new code. You can think of what you have learned so far as the most basic tools of
the trade when it comes to writing games and other Python programs. The data (numbers and strings) and
collections (tuples, list, and dictionaries) are particularly fundamental because you can store every aspect of
a game within them.
In the previous chapter we entered our Python code a line at a time, but now we are going to put the
Note

tically indent for you. Usually the default indentation is four spaces.
Upon running (F5 or Run
Run Module), you should see another window pop up, which is the
console
output, see Figure
Working with Logic
Not just for green-blooded Vulcans, logic is an important part of any software—and that includes games.
Any game needs to make decisions based on information it either has been given or has calculated. If a laser
blast hits the player’s hover tank, the game has to decide if enough damage has been done to destroy it—and
display an explosion animation if it has. This is just an example of a whole host of decisions a computer
game has to make in order to convince us that it is more than just a dumb machine. So please put on your
Spock ears and we will cover logic.
Understanding Booleans
The logic that computers use is
boolean
logic, so called because it was invented by George Boole way back in
Figure 2-1.
ython code in IDLE and the output console window
Listing 2-1.
imple Logic
Running this simple script produces the following output:
Note

also have corresponding numbers: 1 for
.
his goes to the very
Note

common logic mistake is to use the if and and statements like: if fugu and soy_sauce == “tasty:”
thinking that this is asking if both fugu and soy_sauce are tasty.
I
nstead, this simply requires fugu to be
and soy_sauce to be “tasty”.

ruth Table for the And Operator
False and FalseFalse
True and FalseFalse
False and TrueFalse
Table 2-2.

ruth Table for the Or Operator
False or FalseFalse
True or FalseTrue
False or TrueTrue
Here we have reversed the
condition so that Python runs the
code block only if the condition is
not
true (that is, false).
else Statement
Result
False
not False
True
function

ome Built-in Python Functions
FunctionDescription
Finds the absolute value of a number
Displays usage information for any Python object

alculating the Tip on Fugu
25
The only thing you haven’t already encountered in
Note


alculating the Tip on Fugu
Introducing Object-Oriented Programming
You may have heard the term object-oriented programming (OOP) before. But don’t worry if you are
unfamiliar with it, because the concept is remarkably simple.
So what exactly is an object in OOP terms? Well, it can literally be
anything
. In a game we may have
an object for a particle—say, a burning ember emitted from an explosion, or the hover tank that caused
the explosion. In fact, the entire game world could be an object. The purpose of an object is to contain
information and to give the programmer the ability to do things with that information.
When constructing an object, it is usually best to start by working out what information, or
properties

xample Tank Class Definition
27
When Python encounters
, it creates a class called
, which is
derived
from
base
class called
. Deriving from a class means building on what it does. We
could
first create a
class called
, which could handle moving and turning, and then create a tank by
deriving
from it and
adding the ability to fire weapons. The advantage of this approach is that
could be reused to give
other game entities the ability to rotate and move. For this example, we don’t have another class to build on,
so our base class will be
, which is a simple class built into Python itself.
may have given you the impression that
doesn’t do much, but actually it does a lot of useful
things behind the scenes when working with classes—you just don’t use it directly.
Everything in the indented code block after the
statement is the
class definition
. This is where
Adding to our Class

xtended Tank Class
This is a little more complex, as I’m sure you will agree! String formatting can format integers, floats, and

.py
Listing 2-7.
game.py
) first = input("Who fires? ").lower() second = input("Who at? " ).lower() try: first_tank = tanks[first] second_tank = tanks[second] except KeyError as 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("*" * 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!") breakWhen you see any piece of code for the first time (in any language), it can be a little intimidating. But
Note

When you do
, it imports the
class (capital
—which means you can now use
as if you had just cut and pasted it into your script.
owever,
, you have imported the tank namespace, which means you would have to refer to
class as
, as in
. See the section “
ntroducing import” later
31
Next we create a dictionary called
, 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.
The three tanks have the strings
as keys, so we can look them up easily. Once we
create our tanks, we store the number of tanks in
so we can keep count of tanks still in
the game:
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:
)The
not
a key in the
dictionary, then Python will throw a
exception when we try to look
either of them up. This won’t make the script exit because we look up the keys inside a
block, which
says to Python that the code block
may
throw an exception. If a
does occur, Python jumps to the
code under
(which is ignored if no exception occurs).
Inside our
exception handler we first display a brief message to inform the user that they did
Using the Standard Library
Python is packaged with a huge collection of classes and functions known as the
standard library
. This
is why Python is often described as having
batteries included
, because you can take advantage of code
module for more advanced functions—the kind of thing you would find on a scientific calculator.
See Table
for a few of them.
Table 2-5.

ome Functions in the math Module
FunctionDescription

ClassDescription
You won’t be surprised to learn that the
module is used to generate random numbers, although
you may be surprised to learn that the numbers it generates aren’t truly random. That’s because computers

imulator
Wow, just three lines. All this does is import the
module, then call
ten times
and prints the results. The function
Note

ve noticed in
L
that the value of
is never actually used inside the loop.
generates numbers from 0 to 9, but we ignore them because all we are interested in is
repeating the loop ten times.
R
ather than thinking of a name for a value that is never used, it is common to use
a single underscore in its place. So the loop in
L
Although the numbers that Listing
produces appear random, they are actually
pseudorandom
which means they are chosen from a large mathematically generated sequence. Occasionally you may need
to repeat a sequence of pseudorandom numbers—when playing back a demo, for instance. You can tell the
module to start generating numbers from a particular point in the sequence by calling the
function. If you call it twice with the same value, it will cause the
module to reproduce the same
sequence of numbers. Listing
demonstrates how the
function can be used to create predictable
sequences.
Listing 2-9.

If you run this small script, you will see the same sequence of numbers, repeated twice. Have a look at
Table
for a few of the capabilities of the
module.
Summary
We’ve seen that you can use boolean logic to make decisions in Python code. The
statement takes a
boolean expression, such as
, and runs a code block only if that condition results in
. You can
append an
statement with one or more
statements, which run their code block only if the condition
. Logic can be combined using the
operators, and can be reversed using the
operator.
Functions are stored Python code, created with the
statement. When you define functions, you

ome Functions in the random Module
FunctionDescription
Seeds the random number
generator
Have you ever opened up your computer and had a look inside the case? No need to do it now, but you will
find that it is built from a number of parts necessary to deliver your computing experience. The video card
SDL was written in C, a language commonly used for games because of its speed and ability to work
with the hardware at a low level. But developing in C, or its successor C++, can be slow and error prone.
So programmers produced
bindings
to their favorite languages, and SDL can now be used from just about any
To install these, you simply download the .whl file, then use pip to install it by referencing the .whl file
as what you want to install. For example, you may download a .whl named pygame-1.9.2a0-cp34-none-
win32.whl. To install this, assuming you downloaded this file to your downloads directory, you would type

odules in the Pygame Package
Module NamePurpose
Accesses and controls CD drives
Loads cursor images
Accesses the display
Draws shapes, lines, and points
Manages external events
Uses system fonts
Loads and saves an image
Uses joysticks and similar devices
Reads key presses from the keyboard
Loads and plays sounds
Manages the mouse
Plays movie files
Works with music and streaming audio
Accesses advanced video overlays pygame
Contains high-level Pygame functions
Manages rectangular areas
Manipulates sound data
Manages moving images
Manages images and the screen
Manipulates image pixel data
Manages timing and frame rate
Resizes and moves images
Some of the modules you will use in every game. You will always have some sort of display, so the
Figure 3-1.
ello World in Pygame
Listing 3-1.
ello World Redux (helloworld.py)
mouse_image_filename = 'fugu.png'
e need two images for Listing
: one to use as a background and another to draw as our mouse
cursor. You can download the files for this and the other samples from the Source Code/ Download section
The first line imports the
package, which gives us access to all its submodules, such as
. The second line imports a number of functions and constants (values
that don’t change) into the top-level namespace. It isn’t essential to do this in order to use Pygame, but it is
convenient because we don’t have to precede frequently used values with the
namespace. The last
statement imports a single function from
(a module in the standard library). As you may have
guessed, the purpose of
is to immediately finish with the script. Calling it causes the Pygame window
to disappear and Python to close. The script calls
when the user clicks the close button; otherwise, the
user would have no way of closing the window!
p
P
ygame window, you may be able to stop
P
This rather simple line of Python code actually does a lot of work:
It initializes each of the submodules in the
package, which may load drivers and query hardware
so that Pygame is ready to use all the devices on your computer. You can initialize only the modules you
intend to use by calling the
function in each submodule individually; for example,
will initialize the sound module. This can make the script start a little quicker because only the modules you
actually use will be initialized. For games you will require most, if not all, of the modules—so we will stick
with this catchall initialize function. After we call it, we have the full power of Pygame at our disposal!
After initializing Pygame we need to create a display surface:
45

FlagPurpose
Creates a display that fills the entire screen.
Creates a “double-buffered” display. Recommended for
Creates a hardware-accelerated display (must be combined with the
flag).
Creates an OpenGL renderable display.
Creates a resizable display.
Removes the border and title bar from the display.
Table 3-3.

it-Depth Values
Bit DepthNumber of Colors
256 colors, chosen from a larger
Note

P
ygame is unable to give us the exact display we ask for. It may be that the graphics card
doesn't support the features we are requesting. Fortunately,
P
ygame will choose a display that is compatible
with the hardware and emulates the display we actually asked for.
hank you,
P
If all goes well, the call to
The
47
After we draw the background, we want to draw
underneath the usual mouse pointer:

tandard Events
Purpose
p
to (0,0,0) and the color of the font to (0, 255, 0), it will look a
Matrix
-style code.
ve to use your imagination a little!
Listing 3-2.
playing the Message Queueimport pygame
ou run Listing
, you will see a simple black window. If you move your mouse over the window,
you will start to see printed output to the console (see Figure
). These events specify the current position
of the mouse, how far the mouse has moved since the last motion event, and which buttons are currently
pressed. You
Figure 3-2.
utput from the events script
Handling Mouse Motion Events
As you have seen,
events are issued whenever you move the mouse over the Pygame window.
They contain these three values:
buttons—
A tuple of three numbers that correspond to the buttons on the mouse. So
is the left mouse button,
is the middle button (like a mouse
wheel), and
is the right button. If the button is pressed, then its value

sing Keyboard Events to Move a Background

move_x, move_y = 0, 0




if event.key == K_LEFT:


if event.key == K_LEFT:


y+= move_y


screen.blit(background, (x, y))


isting
begins just like Hello World; it imports and initializes Pygame, then loads a background
image. The event loop in this script is different, because it handles
. These key events both
contain the same three values:
key—
This is a number representing the key that was pressed or released. Each
physical key on the keyboard has a constant that begins with
unicode—
This is the
Unicode
value of the key that was pressed. It is produced by
combining the pressed key with any of the modifier keys that was pressed. There is
Posting Events
Generally it is Pygame that creates all the events for you, but you can create your own. You could use this
ability to play back demos (by replicating the player’s input), or simulate the effects of a cat walking across
the keyboard (I like to make my games cat proof).
To send an event, you first construct an event object with
and then post it with
Full-Screen Displays
In Hello World we used the following line to create a Pygame window:
Caution

herefore, it's best to test it in windowed mode first.
tive way to exit the script because the close button is not visible in full-screen mode.
When you go full screen, your video card will probably switch to a different video mode, which will
change the width and height of the display, and potentially how many colors it can show at one time. Video
cards only support a few combinations of size and number of colors, but Pygame will help you if you try to
select a video mode that the card does not support directly. If the size of display you ask for isn’t supported,
Pygame will select the next size up and copy your display to the center of it, which may lead to black borders
at the top and bottom of your display. To avoid these borders, select one of the standard resolutions that
virtually all video cards support: (640, 480), (800, 600), or (1024, 768). To see exactly what resolutions your
display supports, you can use
Note
N
otice how
Listing 3-4.
ull-Screen Example




ccasionally you may want the user to be able to resize a Pygame window, which you typically do by
clicking on the corner of the window and dragging with the mouse. It’s easy enough to do this by using the
flag when you call

sing a Resizable Window





event = pygame.event.wait()
exit()
if event.type == VIDEORESIZE:
Additional Display Flags
There are a few more flags you can use in a call to
Note

, you should call
rather than
.
his does the instant display switch rather than copying screen data.
I promised to cover the font module that we used in the event queue script. The ability to draw text on the
screen can really help with testing scripts; you may also need it to display game instructions, menu options,

iting Your Name to an Image File
his script is so simple that we don’t even need to create a display! When you run Listing
, you won’t
see much happen on the screen, but the code creates an image file called name.png in the same location as
the script. You can open the file with any image viewer software. Saving the surface to a file is done with the
pygame.image module, which we will cover in the next chapter.
The font module provides other functions as well as
objects, which you may occasionally need to
Caution

y from computer to computer, and you cannot always rely on a particular font
being present. If
P
ygame doesn't find the font you are asking for, it will use a default font that may not look the
same.
he solution is to distribute the .ttf files with your game, but make sure you have permission from the
Pygame in Action
Back when I was a youngling, the “scrolly message” was a very popular effect among hobbyist graphics
programmers. A scrolly message, or
marquee
as it is now known, is simply text sliding across the screen from
right to left. Listing
is a Pygame implementation of a scrolly message. It’s not without its faults, the most
major of which is that it moves at an inconsistent speed, and may be faster or slower on different computers.
This is a problem that you will learn how to solve in the next chapter.
Most of this script should be familiar by now, so I won’t break it down. Try tweaking the code to
produce different results. You may also want to insert text of your own choice, which you can do by
modifying the
string at the start of the script.
Listing 3-7.

crolly Message Script









Summary
Creating Visuals
Computer games are very visual in nature, and game developers spend a lot of time working on
manipulating graphics and refining the visuals to create the most entertaining experience for the player.
This chapter gives you a strong foundation in generating visuals for computer games.
Proceeding through this chapter, we will use examples written in Python and using the Pygame module
to illustrate our point. You are not required to understand these programs in full, but you’re encouraged to try!
Using Pixel Power
If you peer closely at your computer screen, you should be able to make out that it is composed of rows

enerating an Image Containing Every Color
CREATING VISUALS
Listing
is unusual for a Pygame script because it is not interactive. When it runs you will see it count
from 1 to 256 and then exit after saving the bitmap file in the same location as the script. Don’t worry that it
is slow

olor Table
ColorRedGreenBlueTuple
Black
000(0, 0, 0)
Blue00255(0, 0, 255)
Green02550(0, 255, 0)
Cyan
0255255(0, 255, 255)
Red
25500(255, 0, 0)
Magenta2550255(255, 0, 255)
Yellow2552550(255, 255, 0)
White255255255(255, 255, 255)
Some early computers were limited to just these gaudy colors; fortunately you can create more subtle
hues nowadays!
It’s well worth experimenting with different values so that you have an intuitive feel for computer-
generated color. With a little practice you should find that you can look at the three color values and make an
CREATING VISUALS
you will see a screen split into two halves. At the top of the screen are three scales—one for each of the red,
green, and blue components—and a circle to represent the currently selected value. If you click anywhere on
one of the scales, it will modify the component and change the resulting color, which is displayed on the lower
half of the screen.
Try adjusting the sliders to (96, 130, 51), which gives a convincing shade of zombie green, or (221, 99, 20)
for a pleasing fireball orange.
Listing 4-2.
Script for Tweaking Colors
CREATING VISUALS
isting
introduces the
module, which is used to draw lines, rectangles, circles, and

unction for Scaling a Color
CREATING VISUALS
If you run Listing
, it will display the color tuple for fireball orange and the darker version:

unction for Saturating a Color
CREATING VISUALS
Blending Colors

imple Lerping Example
his results in the following output. Try to predict what the result of
will be.

lending Colors by Lerping
CREATING VISUALS
67
ou run Listing
, you will see a slider at the top of the screen. Initially it will be at the far left,
representing a factor of 0 (fireball orange). If you click and drag toward the right of the screen, you can
smoothly change the blending factor toward 1 (zombie green). The resulting color is displayed in the lower
half of the screen.
CREATING VISUALS
Creating Images with an Alpha Channel
If you have taken a photo with a digital camera or drawn it with some graphics software, then it probably
won’t have an alpha channel. Adding an alpha channel to an image usually involves a little work with
graphics software. To add an alpha channel to the image of a fish, I used Photoshop, but you can also use
other software such as GIMP (
) to do this. For an introduction to GIMP, see Akkana
Peck’s
Beginning GIMP: From Novice to Professional
(Apress, 2006).
An alternative to adding an alpha channel to an existing image is to create an image with a 3D rendering
package such as Autodesk’s 3ds Max or the free alternative, Blender (
). With this
kind of software you can directly output an image with an invisible background (you can also create several
frames of animation or views from different angles). This may produce the best results for a slick-looking
game, but you can do a lot with the manual alpha channel technique. Try taking a picture of your cat, dog, or
goldfish and making a game out of it!
Storing Images
CREATING VISUALS
LBM (and PBM)
PBM (and PGM, PPM)
XPM
As a rule of thumb, use JPEG only for large images with lots of color variation; otherwise, use PNGs.
Working with Surface Objects
Loading images into Pygame is done with a simple one-liner;
takes the filename of
CREATING VISUALS
provides a
CREATING VISUALS
surfaces have a
clipping area
, which is a rectangle that defines what part of the screen can be drawn to.
CREATING VISUALS

cript That Draws Random Pixels (random.py)
Caution
T
he
he display can be a
CREATING VISUALS
73
Locking Surfaces
Whenever Pygame draws onto a surface, it first has to be
locked
. When a surface is locked, Pygame has full
control over the surface and no other process on the computer can use it until it is unlocked. Locking and
unlocking happens automatically whenever you draw onto a surface, but it can become inefficient if Pygame
has to do many locks and unlocks.
In Listing
there is a loop that calls
Caution
T
here should be the same number of calls to lock as there are to unlock.
I
P
Listing 4-8.
andom Pixels with Locking (randoml.py)
CREATING VISUALS
Blitting
CREATING VISUALS
pygame.draw.rect
This function draws a rectangle onto a surface. In addition to the destination surface and color,

ectangle Test

he pygame.draw Module
FunctionPurpose
Draws a rectangle
Draws a polygon (shape with three or more sides)
Draws a circle
Draws an ellipse
Draws an arc
Draws a line
Draws several lines
Draws an antialiased (smooth) line
Draws several antialiased lines
CREATING VISUALS
There is another way to draw
filled
rectangles on a surface. The

awing Polygons with Pygame
pygame.draw.circle
The
function draws a circle on a surface. It takes the center point and the radius of the circle
(the radius is the distance from the center to the edge). Like the other draw functions, it also takes a value
for the width of the line. If
is 0 or omitted, the circle will be drawn with a line; otherwise, it will be a
solid circle. Listing
draws randomly filled circles on the screen, in a random color.
CREATING VISUALS
Listing 4-11.
andom Circles


awing an Ellipse
CREATING VISUALS
pygame.draw.arc
The
function draws just a section of an ellipse, but only the edge; there is no fill option for
. Like the
ellipse function, it takes a
-style object that the arc would fit into (if it covered the entire ellipse). It also
takes two angles in radians. The first angle is where the arc should start drawing, and the second is where it
should stop. It also takes a

c Test
pygame.draw.line
A call to
CREATING VISUALS
Listing 4-14.
ine Drawing (drawinglines.py)

pygame.draw.lines
Often lines are drawn in sequence, so that each line begins where the previous one left off. The first

awing Multiple Lines (multiplelines.py)
CREATING VISUALS
80
CREATING VISUALS
your computer is doing, the slower the frame rate will be. The good news is that the computer on your
desktop is probably more than fast enough to generate the visuals you want.
Moving in a Straight Line

imple Straight-Line Movement (simplemove.py)
ou run Listing
, you will see the fugu image sliding from left to right. This is exactly the effect we
were looking for, but there is a flaw in the design for Listing
. The problem is that we can’t know exactly
how long it will take to draw the image to the screen. It looks reasonably smooth because we are creating
an extremely simple frame, but in a game the time to draw a frame will vary depending on how much
HINGS MOVE
It’s About Time
The trick to solving this problem is to make the motion
time-based
. We need to know how much time has
passed since the previous frame so we can position everything on the screen accordingly. The

module contains a
object that we can use to keep track of time. To create a clock object, call its
constructor
Once you have a clock object, you should call its member function
Caution
I
f you are not using
P
ython 3+ be sure to divide by a floating-point value of 1000.0.
I
include the floating point, the result will be rounded down to the nearest integer!
So how do we use
to move a sprite? The first thing we need to do is choose a

ime-Based Movement (timebasedmovement.py)
HINGS MOVE
sprite = pygame.image.load(sprite_image_filename)
I

ame Rate and Speed Comparison (frameratecompare.py)
HINGS MOVE
sprite = pygame.image.load(sprite_image_filename)
ou run Listing
, you will see two sprites moving on the screen. The top one moves at 30 frames
per second or as smoothly as your computer will allow; the other simulates a slow computer by updating
only every five frames. You should see that although the movement is very jerky for the second sprite, it does
actually move at the same average speed. So for games that use time-based motion, a slow frame rate will
result in a less pleasant viewing experience but won’t actually slow down the action.
HINGS MOVE
Note
A
lthough well-written games should still be playable at slow frame rates, people will be put off
playing it if the motion is too jerky.
P
I
wouldn’t want to play a game that ran much under 15 frames
per second, it can become very disorienting!
Diagonal Movement

imple Diagonal Movement (diagonalmovement.py)
HINGS MOVE
y += speed_y * time_passed_seconds
T
Creating Vectors
You can calculate a vector from any two points by subtracting the values in the first point from the second.

imple Vector Definition


Figure 5-1.
reating a vector
To define a vector, we can now use
objects. For instance, a call to

produces a
object called
. We can refer to the components of the vector individually as
The first thing we should add to our

ector from Points




esting the
Listing 5-8.
Vector Magnitude Function
Figure 5-2.
Creating a vector
The preceding is where T is the translation vector (AB in our example).
The last few lines create a test vector, and then call the








Executing this script produces the following output:
Vector Addition
for multiply (
). Listing
extends the vector class
with an
Figure 5-3.
ector addition
T
I
Vector Subtraction
Subtracting a vector means going in the
opposite
direction the vector is pointing. If soldier Alpha was forced
his current position to find a point directly behind him. The math for vector subtraction is very similar to
addition, but we subtract from the components rather than add. Listing
a vector from another vector, which you can add to the


ector Negation

ector Multiplication and Division

HINGS MOVE
Note

but it isn’t used very often in games and you
So how might soldier Alpha use vector multiplication—or more accurately, how would the game
programmer use it? Vector multiplication is useful to break up a vector into smaller steps based on time.
If we know Alpha can cover the distance from A to B in 10 seconds, we can calculate the coordinates where
Alpha will be after every second by using a little vector code. Listing
shows how you might do this
using the
class.
Listing 5-14.

alculating Positions
Figure 5-4.
ultiplying a vector by a scalar
If you multiply any vector by 2.0, it will double in size; if you divide a vector by 2.0 (or multiply by 0.5),
it will halve the size. Multiplying a vector by a number greater than 0 will result in a vector that points in the
same direction, but if you were to multiply by a number less than 0, the resulting vector would be “flipped”
and point in the opposite direction (see Figure
HINGS MOVE
This produces the following output:
Listing 5-15.
100
Now you should have a gameobjects directory in the same directory as the scripts you are writing as you
follow along, and vector2.py should be within the gameobjects directory.
Listing
implements time-based movement using vectors. When you run it, you will see a sprite
sitting motionless on the screen, but once you click the screen, the code will calculate a vector to the new

sing Vectors for Time-Based Movement (vectormovement.py)
The destination calculation may require a little explanation. It uses the
class to find a point that
would put our sprite directly over the mouse coordinate. The

alculating the Destination Coordinate the Long Way
103
EPTING USER
I
NP
U
104
Understanding Keyboard Control
Most keyboards in use today are
QWERTY
Note
A
lthough it is the most common, QW
ERT
Y isn’t the only keyboard layout; there are other keyboards
such as
Z
ERT
Y and Dvorak.
he same keyboard constants may be used, but the keys may be at a different
location on the keyboard.
I
f you give the player the option of selecting their own keys for use in the game, they
can select the controls that are most appropriate for their keyboard.
EPTING USER
I
NP
U
105
In many games, you may have a key to crouch, move forward, strafe a bit, and move slowly. Maybe
while you’re doing this diagonal-crouched-slow-strafe, you want to switch to your grenade by pressing the
number 5. You may find that nothing happens when you press 5! The horror! If only you had bought the Pro
Gamer X ”Over 9000” keyboard!
Not only should you consider the fact that your players may not have the best keyboard, keep in
mind they only have ten total fingers anyway, but usually only five to really work with because one hand
is likely on a mouse. There are plenty of gamers, however, that do make use of pressing two or more
keys with one finger.
Also, you may want to consider those who use gaming pads, where the number of buttons might be
severely limited.

esting Pressed Keys (keydemo.py)
EPTING USER
I
NP
U
106
After Listing
EPTING USER
I
NP
U
107
—This function takes a

imple Direction Vectors
Vector
Left
Right
Down
In addition to horizontal and vertical movement, we want the user to be able to move diagonally by
pressing two keys at the same time. For example, if the Up and Right keys are pressed, the sprite should
move diagonally toward the top right of the screen. We can create this diagonal vector by adding two of the
simple vectors. If we add Up
and Right
EPTING USER
I
NP
U
108
Listing
implements this directional movement. When you run it, you see a sprite that can be moved
horizontally or vertically by pressing any of the cursor keys, or moved diagonally by pressing two cursor keys
in combination.
If you run Listing
without modifying our vector2.py file, you find an error that is generated by the
ou are attempting to divide by zero, then x and y must be zero anyway. Thus, you can solve it very
Figure 6-1.
agonal vectors by combining simple vectors
109
Listing 6-2.
Simple Directional Movement (keymovement.py)
EPTING USER
I
NP
U
110
Listing

ee Rotation Control (keyrotatemovement.py)
EPTING USER
I
NP
U
T
isting
works in a similar way to the previous example, but it calculates the heading differently.
Rather than create a heading vector from whatever keys are pressed, we create the heading from the rotation
of the sprite (stored in the variable
). It is this value that we modify when the appropriate
key is pressed. When the Right key is pressed, we add to the sprite rotation, turning it one way. And when the
Left key is pressed, we subtract from the rotation to turn it in the opposite direction.
To calculate the heading vector from the rotation, we must calculate the
sine
cosine
of the angle,
which we can do with the
functions found in the
module. The
function calculates
the x component, and
calculates the y component. Both functions take an angle in
radians
(there are
2 * pi radians in a circle), but because Listing
uses degrees it has to convert the rotation to radians by
multiplying by pi and dividing by 180. After we assemble the heading vector from the two components, it can
be used as before to give us time-based movement.
EPTING USER
I
NP
U
112
Before Listing
displays the sprite, the sprite is rotated visually so we can see which way it is facing.
This is done with a function from the
module called
, which takes a surface plus an
Figure 6-2.
otating a surface changes its size
The mouse has been around for almost as long as the keyboard. Mouse design didn’t change much for many
years—the devices became a little more ergonomic (hand-shaped) but the design remained the same.
Classic mice have a rubber-coated ball underneath that rolls over the desk or mousepad. The
movement of the ball is picked up by two rollers inside the mouse that are in contact with the ball.
Nowadays, almost all mice are laser mice, offering more precision. Gone are the days where friends can
remove each other’s mouse ball as a practical joke, but now we can always tape paper over the laser hole for
just as much fun.
As time goes on, more and more mice also have various buttons. Almost all have a mouse wheel that
both rolls and can act as a third clicker. There are many mice with lots of various buttons all over as well.
Games often make use of these mice innovations. Extra buttons always come in handy for quick access
to game controls, and the mouse wheel could have been made for switching weapons in a first-person
shooter! And of course the extra accuracy of laser mice always comes in handy when picking off enemies
with a sniper rifle.
EPTING USER
I
NP
U
113
Rotational Movement with the Mouse
You have seen that drawing a mouse cursor on the screen is quite straightforward: you simply need to
arning
I
f you’re planning to copy, paste, and run this code, take note that, to exit, you will
use your mouse. You will exit the game using the
E
Listing 6-4.
otational Mouse Movement (mouserotatemovement.py)
114
EPTING USER
I
NP
U
115
To use the mouse to control sprite rotation, Listing
has to enable
virtual infinite area
for the mouse,
which prevents Pygame from restricting the mouse to the physical screen area. This is done with the
following two lines:
116
Mouse Gameplay
The humble mouse can allow you to be quite creative in a game. Even a simple cursor can be a great
gameplay tool for puzzle and strategy games, where the mouse is often used to pick and drop game elements
in the game arena. These elements could be anything from laser-reflecting mirrors to bloodthirsty ogres,
depending on the game. The actual mouse pointer doesn’t need to be an arrow. For a god game, it would
probably be the omnipotent hand of a deity or perhaps a mysterious alien probe. The classic
point ‘n’ click
adventure games also made excellent use of the mouse. In these games, the game character would walk over
to whatever the player clicked on and have a look at it. If it was a useful object, it could be stored away for use
later in the game.
For games with more direct control of the player character, the mouse is used for rotation or movement.
A flight sim may use the x and y axes of the mouse to adjust the pitch and yaw of the aircraft so that the
player can make fine adjustments to the trajectory. A simple way to do this in Pygame would be to add the
mouse onto the angle of the aircraft. I also like to use the mouse for first-person shooters and use the x axis
for rotating left and right, and the y axis for looking up and down. This feels quite natural because heads tend
to move in that way; I can rotate my head to either side as well as look up and down. I can also tilt my head to
either side, but I don’t do it very often!
You can also combine mouse and keyboard controls. I especially like games that use the keyboard for
movement and the mouse for aiming. A tank, for example, might be moved about with the cursor keys, but
EPTING USER
I
NP
U
117
—Creates a new joystick object that is used to access
all information for that stick. The constructor takes the ID of the joystick—the first
joystick is ID 0, then ID 1, and so on, up to the number of joysticks available on
the system.
The first three functions in the joystick module are used in the initialization process and aren’t often
called manually. The other two functions are more important because we will need them to find out how
many joysticks are plugged into the computer and to create
objects for any of the sticks we want
EPTING USER
I
NP
U
118
Listing 6-5.
playing the Joystick Events (events.py)

hen you run Listing
and press some of the buttons on your joystick, you should see the
and corresponding
for each button press (see Figure
). If you wiggle the
119
Figure 6-3.
Displaying the joystick events
EPTING USER
I
NP
U
120
The d-pad, a small circular or cross-shaped button on the joypad, is used to indicate a direction by pressing
an edge, usually with the thumb. If you were to look underneath the d-pad, you would see that there are four
switches arranged in a cross. When you press the pad in any direction, you also push down one or two of
Note
T
here aren’t any up and down events for the d-pad because when it is released, it springs back to
the middle and another JOY
HAT
MO
TI
O
N
We can also bypass the events for the d-pad and ask Pygame for the current state of the d-pad.
The first step is to find out how many d-pads a joystick has (there could be none), which we can do with the

sing the D-pad to Scroll (hatscroll.py)
EPTING USER
I
NP
U
121
print("Sorry, you need a joystick for this!")
ou can find your own map to use in this code. I recommend going into Google search and typing in
Note
T
he y axis always follows the x axis, so the first stick uses axis index 0 and 1.
I
analog stick available, it will use slot 2 and 3.
In addition to the
EPTING USER
I
NP
U
122
Listing
calculates an additional vector,
, from the x and y axes. This vector isn’t
normalized because we will be using it to indicate
how fast
we want to move, in addition to the
direction
we
want to move in. We still need to multiply by a value for speed, because the axes range from –1 to +1, which
would result in very slow movement.
Listing 6-7.

crolling with the Analog Stick (analoghatscroll.py)
EPTING USER
I
NP
U
123
ugh Listing
simply pans an image around the screen, it could be the basis for a scrolling map
in a strategy or god game.
Dealing with Joystick Dead Zones
Because analog sticks and other axis devices are mechanical things, they suffer from wear and tear, and even
brand-new controllers can have imperfections. This can result in the stick wobbling a tiny amount when it
is not being manipulated. If you see a constant stream of
events without touching anything,
EPTING USER
I
NP
U
124
Figure 6-4.
he joystick demo script in action
125
Listing 6-8.
Joystick Demo (joystickdemo.py)
126
127
129
Take Me to Your Leader
Placing a player character in a convincing world is only part of creating a game. To make a game fun, you
need to present the player with a number of challenges. These may come in the form of traps and obstacles,
but to really entertain your players you need to have them interact with non-player characters (NPCs)—
characters that appear to act with a degree of intelligence or awareness in the game. The process of creating
these NPCs is called artificial intelligence (AI). In this chapter, we will explore some simple techniques that
you can use to give your game characters a life of their own.
Creating Ar
You may have looked in the Pygame documentation for a
module. There isn’t one, because
each game can have vastly different requirements when it comes to creating NPCs. The code for an ape
ME TO YOUR LEADER
130
What Is Intelligence?
Intelligence is a difficult thing to define, even for AI programmers. I’m confident that I am intelligent and
self-aware, but I can only assume that others are intelligent because they are like me in many ways. Other
people talk, move, check their e-mail, and take out their trash like I do—so I
assume
they are intelligent.
Similarly, in a game if a character behaves in a way that an intelligent thing would, then the player will
assume it is intelligent. The programmer may know that the actions of a character are simply a result of a few
pages of computer code, but the player will be oblivious to that fact. As far as the player is concerned, if it
walks like a zombie, moans like a zombie, and eats people like a zombie, then it’s a zombie!
So intelligence in a game is an illusion (it may be in real life as well). The code to create this illusion
doesn’t differ a great deal from the code in the previous chapters. You will use the same basic tools of Python
strings, lists, dictionaries, and so forth to build classes that are effectively the
brains
of your NPCs. In fact,
Python is probably one of the best languages for writing AI because of its large range of built-in objects.
Exploring AI
Artificial intelligence isn’t essential to creating an entertaining game. I used to love to play classic platform
games where the hero has to leap from platform to platform and brazenly jump on the heads of monsters.
Although the monsters in these games are NPCs, their actions are a little rudimentary to be considered

seudocode for a Platform Monster
The particular monster in Listing
doesn’t have any awareness of its surroundings other than being

seudocode for Imp AI
ME TO YOUR LEADER
131
The imp can be in one of two states:
exploring
seeking
. The current state of the imp is stored in the
value of
, and indicates which block of code currently controls the imp’s actions. When the imp
is exploring (i.e.,
), it will walk aimlessly around the map by picking a random
heading. But if it sees the player, it will switch to the second state of
. An imp that is in seeking
mode will head toward the player and fire as soon as it is in range. It will keep doing this as long as the player
Note
T
his imp is not the smartest of underworld denizens. If the player can no longer be seen, the imp will
stop seeking, even if the player has just hidden behind a tree! Fortunately we can build on the state machine
to create a smarter class of imp.
Implementing State Machines
The two states for the imp’s brain form a very simple state machine. A state generally defines two things:
What the NPC is doing at that moment
At what point it should switch to another state
Figure 7-1.
mp state machine
ME TO YOUR LEADER
132
In addition to the current behavior and conditions, states may also contain
entry actions
exit
actions
Note
E
ven though we are using an insect theme for this simulation, the
applicable to many scenarios. If we were to replace the ants, spiders, and leaves with giant “mech” robots,
tanks, and fuel drops, then the simulation would still make sense.
Game Entities
Although we have three different types of entities, it is a good idea to come up with a
base
class for a game
entity that contains common properties and actions. That way, we won’t need to duplicate code for each of
the entities, and we can easily add other entities without much extra work.
An entity will need to store its name (
), as well as its current location,
destination, speed, and the image used to represent it onscreen. You may find it odd that the
entity

he Base Class for a Game Entity


ME TO YOUR LEADER
133

orld Class
self.entity_id = 0 # Last entity id assigned
AKE ME TO YOUR LEADER
134
ME TO YOUR LEADER
135
To store entities in a dictionary, we need a value to use as a key, which could be a string, a number,
or another value. Thinking of a name for each ant would be difficult, so we will simply number the ants
sequentially: the first ant is #0, the second is #1, and so on. This number is the entity’s
, and is stored in
every
object so that we can always locate the object in the dictionary (see Figure
Figure 7-2.
he entities dictionary
Note
A
dictionary that maps incremental numbers to its values is similar to a list, but the keys won’t shuffle
nt #5 will still be
nt #5, even if
Most of the functions in the
class are responsible for managing the entities in some way. There is
function to add an entity to the world, a
function to remove it from the world,
ME TO YOUR LEADER
136
Note

P
C, you should generally limit the information available to it, because like
P
Cs may not necessarily be aware of everything that is going on in the world. We simulate this

he Ant Entity Class
GameEntity.__init__(self, world, "ant", image)
ME TO YOUR LEADER
137

ctions for the Ant States
Exploring
Walk toward a random point in the world.
Seeking
Head toward a leaf.
Delivering

inks from Exploring State
Seen a leaf?
Seeking
Spider attacking base?Hunting
ME TO YOUR LEADER
138
Figure 7-3.
nt state machine

ase Class for a State
self.name = name
ME TO YOUR LEADER
139
efore we build the states, we need to build a class that will manage them. The
class
(see Listing
) stores an instance of each of the states in a dictionary and manages the currently active
state. The
function runs once per frame, and calls the
on the active state— to do whatever
the state was designed to do; the exploring state will select random places to walk to, the
seeking
state will
move toward the leaf, and so forth. The
function also calls the state’s
function to
check all the link conditions. If

he State Machine Class
self.active_state = None # The currently active state

ME TO YOUR LEADER
140
Now that we have a functioning state machine class, we can start implementing each of the individual
states by deriving from the
class and implementing some of its functions. The first state we will
implement is the exploring state, which we will call
(see Listing
). The entry actions
Caution
R
andom numbers are a good way to make your game more fun, because predictable games can
he Exploring State for Ants (AntStateExploring)
State.__init__(self, "exploring")
ME TO YOUR LEADER
141
ou can see from Listing
, the code for an individual state need not be very complex because the
AKE ME TO YOUR LEADER
142
Listing 7-9.
Figure 7-4.
The ant simulation
AKE ME TO YOUR LEADER
143
AKE ME TO YOUR LEADER
144
AKE ME TO YOUR LEADER
145
AKE ME TO YOUR LEADER
146
AKE ME TO YOUR LEADER
147
AKE ME TO YOUR LEADER
148
AKE ME TO YOUR LEADER
149
AKE ME TO YOUR LEADER
150
ME TO YOUR LEADER
151
Summary
Making a non-player character behave in a realistic fashion is the goal of artificial intelligence in games.
Good AI adds an extra dimension to the game because players will feel that they are in a real world rather
than a computer program. Poor AI can destroy the illusion of realism as easily as glitches in the graphics
or unrealistic sounds—possibly even more so. A player might be able to believe that a crudely drawn stick
figure is a real person, but only as long as it doesn’t bump into walls!
The apparent intelligence of an NPC is not always related to the amount of code used to simulate
it. Players will tend to attribute intelligence to NPCs that is not really there. In the ant simulation that we
created for this chapter, the ants will form an orderly queue when chasing the spider. A friend of mine saw
153
Games generally try to mimic the real world, or create a world that is not so far from reality that the player
will still in some way be able to identify with it. In the past this required a real leap of faith on behalf of the
MOVING INTO THE
154
Listing 8-1.
Illusion of Depth (parallaxstars.py)
MOVING INTO THE
HIRD
D
I
M
155
hen you run Listing
, you will see a fairly convincing star field with stars at various distances
moving past the screen. Although the star field looks 3D, you won’t find anything particularly unfamiliar in
the code; all it does is move a number of points across the screen at varying speeds. The impression of depth
is a result of your brain assuming that quick objects are close to you and slower objects are farther away.
To store the position of an entity in a 2D game, you use a
coordinate system
with two components, x and y,
that correspond to the physical pixels on the screen. For a 3D game you need to use a coordinate system with
an additional component called z (see Figure
). This extra component is used to measure the distance
into
out from
, the screen. Of course, Pygame can’t actually draw anything using 3D coordinates because
the screen is flat. So 3D coordinates will eventually have to be converted to 2D before they are used to render
anything to the screen. We will cover how to do this later in the chapter, but first we need to know how to
store a 3D coordinate with Python.
In a 3D coordinate system, x points right and y points up. This is different from the coordinate system
we have been using to create 2D graphics, where y points
down
the screen. In 3D, if you increase the y
component, the coordinate will move
the screen and not down.
Figure 8-1.
ree-dimensional coordinate system
MOVING INTO THE
HIRD
D
I
M
156
The z axis in a 3D coordinate system can point in one of two ways depending on the graphics
technology used; either it points
into
the screen (away from the viewer), or it points
out of
the screen (toward
the viewer). In this book, we will be using a coordinate system with a positive z that points out of the screen.
Figure
shows the 3D coordinate system with a spy droid—represented by a circle—at coordinate
(7, 5, 10). Because this isn’t a pop-up book, the extra axis is represented as a diagonal line.
The units for a 3D coordinate could represent anything depending on the scale of the game. If you are
using a dedicated class will make calculations easier. Listing
shows how we might begin to define a 3D
class.
Figure 8-2.
oid in a 3D coordinate system
MOVING INTO THE
HIRD
D
I
M
157
Listing 8-2.
eginning a 3D Vector Class
self.y = y

sing the Game Objects Vector3 Class
B = Vector3(10, 16, 12)
MOVING INTO THE
HIRD
D
I
M
158
Time-Based Movement in 3D
We can use the
class to do time-based movement in 3D in much the same way as we do in two

ulder-mounted plasma rifle to the droid’s location.
Figure 8-3.
MOVING INTO THE
HIRD
D
I
M
159
Listing 8-4.
B = (7, 5, 10)
MOVING INTO THE
HIRD
D
I
M
160
Listing 8-5.
unction That Performs a Parallel Projection
Figure 8-5.
ube rendered with a perspective projection
Figure 8-4.
ube rendered with a parallel projection
MOVING INTO THE
HIRD
D
I
M
161
Listing 8-6.
unction That Performs a Perspective Projection
Figure 8-6.
he viewing distance in a perspective projection
MOVING INTO THE
HIRD
D
I
M
162
p
You can accomplish a lot in 3
D
graphics by looking up formulas on the
I
D
alculating the Viewing Distance
Figure 8-7.
ield of view
MOVING INTO THE
HIRD
D
I
M
163
A 3D World
Note

camera in a 3
D
scene is just the current viewpoint; it may be the view from the player character’s
eyes, or any other view in the game.
Figure 8-8.
imple 3D engine in Pygame
MOVING INTO THE
164
Listing 8-8.
Simple 3D Engine (simple3d.py)
MOVING INTO THE
165
MOVING INTO THE
166
MOVING INTO THE
HIRD
D
I
M
167
Listing
starts out by creating a list of
objects with coordinates along the edges of a cube. The
points are then sorted by their z components, so that when they are rendered, the points nearer the viewer
are drawn first. Otherwise, distance points may overlap those that are close to the viewer and it will break the
illusion of 3D.
Inside the main loop, the camera position is changed depending on which keys are currently pressed.
You can see that the code to move a 3D point is very similar to moving a 2D sprite, with only an additional
z component that moves forward and back in the 3D scene. The code to update the position with time-
based movement is actually identical to the 2D calculation; it just used
objects rather than
objects.
Next in the code is a loop that draws all the points in the scene. First, the point is adjusted so that it is
relative to the camera by subtracting the
variable. If the resulting z component is greater
than 0, it means that the point is in front of the camera and may be visible—otherwise, there is no point in
drawing it. When the point is in front of the camera, it is projected by multiplying the x and y components
by the viewing distance and dividing by the z component. The y axis is also flipped to point in the right
direction for the 2D drawing functions. Finally the 2D coordinate is adjusted to place the “world” in the
center of the screen by adding half the width (
) to the x component and half the height (
to the y component.
The remaining code draws a small diagram that shows how the viewing distance relates to the width of
the screen and the fov. It also displays a few pieces of information onscreen so that you can see what effect
the key presses have.
If you want to experiment with this demonstration, try adding other lists of points that create other
objects, such as pyramids and spheres. You might also want to make these “objects” move in 3D in the same
way as we have done with 2D sprites in the preceding chapters.
Summary
Games with 3D visuals have the most potential to draw players in and keep them entertained. This is true
not because the graphics are more realistic—early 3D games actually looked crude in comparison to their
2D counterparts—but because they feel more
natural
. Objects in a 3D game can rotate and be viewed at
different angles, just like in the real world.
Storing information about 3D points and directions is a simple extension to 2D; we just need an extra
component for the extra dimension. If you use the
class from the Game Objects library, you will find
that much of the math is virtually identical to 2D because the vector class handles the extra component. All
that we have done differently so far in the move to 3D is to
project
the points onto the screen to use Pygame’s
drawing capabilities. There are actually many types of projection, but perspective projection is by far the
most common because it creates natural-looking scenes.
In the next chapter we will explore how to create rich 3D scenes with OpenGL, the technology behind
many commercial games, including the Quake series. You will discover that some of what we have covered
in this chapter is actually done automatically by OpenGL, but I haven’t wasted your time—understanding
projection and field of view will help you when you’re creating OpenGL-powered visuals.
169
You’ve seen how to take a point in three-dimensional space and
project
it onto the screen so that it can be
rendered. Projection is only part of the process of rendering a 3D scene; you also need to manipulate the
points in the game to update the scene from frame to frame. This chapter introduces the
matrix
, which is a
kind of mathematical shortcut used to manipulate the position and orientation of objects in a game.
You will also learn how to use Pygame with OpenGL to access the 3D graphics capabilities of your
graphics card to create impressive visuals, on par with commercial games.
Long before
that movie
, mathematicians and game programmers were using matrices. A matrix is a grid
of numbers that can be any size, but in 3D graphics the most useful matrix is the 4 × 4 matrix. This section
covers how to use matrices to position objects in a 3D world.
It takes a few different pieces of information to describe how a 3D object will look in a game, but its
basic shape is defined by a collection of points. In the previous chapter we created a
model
of cube by
building a list of points along its edges. More typically the list of points for a game model is read from a file
created with specialized software. However the model is created, it has to be placed at a location in the game
world, pointing in an appropriate direction and possibly scaled to a new size. These
transformations
points in a 3D model are done with matrices.
Understanding how matrices work would require a lot of math that is beyond the scope of this
book. Fortunately you don’t need to know how they work to be able to use them. It is more important to
XPLOR
I
NG THE
T
H
I
R
D
D
IM
ENS
I
170
The first three rows represent an axis in 3D space, which is simply three vectors that point in the x, y,
and z directions of the transformation. It helps to think of these three vectors as
right
forward
to
avoid confusion with the x, y, and z axes of the world. These vectors are always relative to the object being
transformed. For example, if the game character was a humanoid male, then the matrix may be in the center
of his chest somewhere. The right vector would point out from his right arm, the up vector would point out
of the top of his head, and the forward vector would point forward through his chest.
The fourth row is the matrix
translation
, which is where the coordinate (0, 0, 0) would end up if it were
transformed with this matrix. Because most 3D objects are modeled around the origin, you can think of the
translation as the position of the object, once it has been transformed.
If we transformed a tank with this matrix, where would it end up? Well, the translation is (0, 0, 0) so it
would be in the center of the screen. The
right
vector is (1, 0, 0), which would mean that the right side of the
tank was facing in the direction of the x axis. The
vector is (0, 1, 0), which faces the top of the screen in the
positive y direction. Finally, the
forward
Note

S
ome books display matrices with the rows and columns flipped, so that the translation part is in the
right column rather than the bottom row.
G
because it can be more efficient to store matrices in memory this way.
Using the Matrix Class
The Game Objects library contains a class named
Figure 9-1.
omponents of a matrix
XPLOR
I
NG THE
T
H
I
R
D
D
IM
ENS
I
171
The first line imports the
class from the
module. The second line
creates a
object, which defaults to the identity matrix, and names it
. The third line prints
the value of identity to the console, which results in the following output:
Figure 9-2.
atrix components
XPLOR
I
NG THE
T
H
I
R
D
D
IM
ENS
I
172
Individual rows of the matrix can be extracted by calling the
p
hey are a good way of catching problems in your
code early on. If you want
P
ython to ignore assert statements in the code, invoke the script with
Listing 9-1.

ow Attributes for Matrix44 Objects
Row 0
Row 1
Row 2
Row 0
Row 1
Row 2
Row 3
XPLOR
I
NG THE
T
H
I
R
D
D
IM
ENS
I
173
Translation Matrix
translation matrix
is a matrix that adds a vector to the point being transformed. If we transform the points
of a 3D model by a translation matrix, it will move the model so that its center is at a new coordinate in the
world. You can create a translation matrix by calling
, which takes the translation
vector as three values. The following code creates and displays a translation matrix:
This produces the following output:
[ 0 1 0 0 ][ 0 0 1 0 ][ 10 5 2 1 ]The first three rows of a translation matrix are the same as the identity matrix; the translation vector is
stored in the last row. When
is transformed, its components are added to the translation—in the same
way as vector addition. Every object in a 3D game must be translated; otherwise, everything would be
located in the center of the screen!
Manipulating the matrix translation is the primary way of moving a 3D object. You can treat the
translation row of a matrix as the object’s coordinate and update it with time-based movement. Listing
an example of how you might move a 3D model (in this case, a tank) forward, based on its current speed.
Listing 9-2.

xample of Moving a 3D Object
The first line in Listing
Caution

You can only treat the forward vector as a heading if the matrix has not been scaled (see the
next section). If it has, then you must normalize the forward vector so that it has a length of one. If the tank in
was scaled, you could calculate a forward heading with
D
174
Scale Matrix
A scale matrix is used to change the size of a 3D object, which can create useful effects in a game. For
example, if you have a survival horror game with many zombies wandering about a desolate city, it might
look a little odd if they were all exactly the same size. A little variation in height would make the hordes of
undead look more convincing. Scale can also be varied over time to produce other visual effects; a crowd-
pleasing fireball effect can be created by rapidly scaling a red sphere so that it engulfs an enemy and then
slowly fades away.
The following code creates a scale matrix that would double the dimensions of an object. When we use
it to transform
XPLOR
I
NG THE
T
H
I
R
D
D
IM
ENS
I
175
Rotation Matrix
Every object in a 3D game will have to be rotated at some point so that it faces in an appropriate direction.
Most things face in the direction they are moving, but you can orient a 3D object in any direction you wish.
Rotation is also a good way to draw attention to an object. For example,
power-ups
Figure 9-3.
otation matrices
D
176
When working with 3D rotation, I find it helpful to visualize an axis for my head, where (0, 0, 0) is in
my brain somewhere. The x axis points out of my right ear, the y axis points out the top of my head, and
the z axis points out of my nose. If I were to rotate my head around the x axis, I would nod my head up and
down. Rotating around the y axis would make me turn my head left or right. A rotation around the z axis
would make me tilt my head quizzically from side to side. Alternatively, you can use your thumb and first
two fingers to point along the positive direction of each axis and physically rotate your hand when you are
thinking about rotations.
Matrix Multiplication
Often in a game you will need to do several transformations to a 3D object. For a tank game you would likely
want to
translate
it to a position in the world and then
rotate
it to face the direction it is heading. You could
transform the tank with both matrices, but it is possible to create a single matrix that has the combined effect
by using
matrix multiplication
Figure 9-4.
A rotation about the z axis
XPLOR
I
NG THE
T
H
I
R
D
D
IM
ENS
I
177
The result is also a translation matrix. The last row (the translation part) in the matrix is (–2, 12, 6),
which is the combined effect of translating by (5, 10, 2) and (–7, 2, 4). Matrices do not need to be of the same
XPLOR
I
NG THE
T
H
I
R
D
D
IM
ENS
I
178
Pressing the Q and A keys rotates the cube around the x axis; pressing W and S rotates it around the y
axis; and pressing E and D rotates it around the z axis. The resulting transformation matrix is displayed as the
cube rotates (see Figure
). Look at the code (in bold) that creates the matrix; it first creates an x rotation
and then multiplies it by a y rotation, followed by a z rotation.
Figure 9-5.
ansformations in action
p
quicker way to create a transformation about all three axes is to use the
function,
Listing 9-3.
atrix Transformation in Action (rotation3d.py)
D
179
D
180
D
181
XPLOR
I
NG THE
T
H
I
R
D
D
IM
ENS
I
182





he matrices in Listing
transform the points of a cube to their final positions onscreen. Games do
many such transforms in the process of rendering a 3D world, and have more sophisticated graphics than
can be produced with 2D sprites. In the following section, you will learn how to
join up
the points in a model
and use lighting to create solid-looking 3D models.
Today’s graphics cards come with chips that are dedicated to the task of drawing 3D graphics, but that wasn’t
always the case; in the early days of 3D games on home computers, the programmer had to write code to
draw the graphics for each game. Drawing polygons (shapes used in games) in software is time consuming,
as the processor has to calculate each pixel individually. When graphics cards with 3D acceleration became
popular, they freed up the processor to do work on other aspects of the game, such as artificial intelligence,
XPLOR
I
NG THE
T
H
I
R
D
D
IM
ENS
I
183
Installing PyOpenGL
Although OpenGL is probably already on your system, you will still need to install PyOpenGL, which is a
module that interfaces the OpenGL drivers on your computer with the Python language. You can install
PyOpenGL with pip, by opening cmd.exe, bash, or the shell you happen to use and doing:
For more information regarding PyOpenGL, see the project’s website at
p
E
asy Install is a very useful tool, because it can find and install a huge number of
P
ython
modules automatically.
Initializing OpenGL
The PyOpenGL module consists of a number of functions, which can be imported with a single line:
This line imports the OpenGL functions, which begin with
, for example,
, which we will
XPLOR
I
NG THE
T
H
I
R
D
D
IM
ENS
I
184
OpenGL Primer
OpenGL contains several matrices that are applied to the coordinates of what you draw to the screen. The
two that are most commonly used are called
. The projection matrix
) takes a 3D coordinate and projects it onto 2D space so that it can be rendered to the screen.
We’ve been doing this step manually in our experiments with 3D—it basically does the multiplication by
view distance
and divides by the z component. The
model view
matrix is actually a combination of
two matrices: the
model

esizing the Viewport
The
function in Listing
takes the width and height of the screen, and should be called when
the display is initialized or the screen dimensions change. The call to
tells OpenGL that we want
to use the area of the screen from coordinate (0, 0), with a size of (
), that is, the entire screen.
The next line calls
, which tells OpenGL that all further calls that work with
matrices will apply to the projection matrix. It is followed by a call to
XPLOR
I
NG THE
T
H
I
R
D
D
IM
ENS
I
185
Initializing OpenGL Features
The
function is enough to start using OpenGL functions to render to the screen, but there are a few

nitializing OpenGL
glClearColor(1.0, 1.0, 1.0, 0.0)
he first thing that the
function does is call
with
, which tells OpenGL to
enable the
Z buffer
. This ensures that objects that are far from the camera aren’t drawn over objects that are
near to the camera, regardless of the order that we draw them in code.
The
function is used to enable OpenGL features, and
is used to disable them. Both
functions take one of a number of uppercase constants, beginning with
. We will cover a number of these
Figure 9-6.
he viewing frustum
XPLOR
I
NG THE
T
H
I
R
D
D
IM
ENS
I
186
The second line in
p
O
pen
GL
driver supports with
Figure 9-7.
enGL light sources
XPLOR
I
NG THE
T
H
I
R
D
D
IM
ENS
I
187
Drawing in Three Dimensions
Now that we have initialized OpenGL and created a light source, we can start drawing 3D shapes. OpenGL
supports a number of
primitives
that you can use to build a 3D scene, such as points, lines, and triangles.
Each takes a number of pieces of information, depending on the type of primitive and the OpenGL features
that are enabled. Because of this, there aren’t single functions for each primitive as there are in 2D Pygame.
The information is given in a number of function calls, and when OpenGL has all the information it needs, it
can draw the primitive.
To draw a primitive in OpenGL, first call
, with one of the primitive constants (see Table
).
Next, send OpenGL the information it needs to draw the primitive. At a minimum it will need a number
of 3D points, specified with the
vertex
is a point that forms part of a shape), but you
can give it other information, such as color with the
function. Once all the information has been
given, call
, which tells OpenGL that all the information has been provided and it can be used to
draw the primitive.
Note

should always come after other information for a vertex is given.
Listing
is an example of how you might draw a red square with OpenGL. The first line tells OpenGL
that you want to draw quads (shapes with four points). The next line sends the color red (1.0, 0.0, 0.0), so all
vertices will be red until the next call to
. The four calls to
send the coordinates of each of
the corners of the square, and finally, the call to
tells OpenGL that you have finished sending vertex
information. With four vertices, OpenGL can draw a single quad, but if you were to give it more, it would
draw a quad for every four vertices you send it.
Table 9-2.

enGL Primitives
Draws dots
Draws individual lines
Draws connected lines
Draws connected lines, with the last point joined to the first
Draws triangles
Draws triangles where each additional vertex forms a new
triangle with two previous vertices
Draws quads (shapes with four vertices)
Draws quad strips where every two vertices are connected to
the previous two vertices
Draws polygons (shapes with any number of vertices)
XPLOR
I
NG THE
T
H
I
R
D
D
IM
ENS
I
188
Listing 9-6.
seudocode for Drawing a Red Square
Normals
If you have OpenGL lighting enabled, you will need to send an additional piece of information for primitives
called a
normal
, which is a unit vector (a vector of length 1.0) that faces outward from a 3D shape. This vector
is necessary for calculating the shading from lights in the scene. For example, if you have a cube in the center
of the screen aligned along the axis, the normal for the front face is (0, 0, 1) because it is facing along the
positive z axis, and the normal for the right face is (1, 0, 0) because it faces along the x axis (see Figure
To send a normal to OpenGL, use the
function, which takes three values for the normal
vector, or the
function, which takes a
sequence
of three values. For example, if the square
in Listing
Figure 9-8.
ormals of a cube
XPLOR
I
NG THE
T
H
I
R
D
D
IM
ENS
I
189
If you have many primitives to draw—which is typically the case for a 3D game—then it can be slow to make
all the calls necessary to draw them all. It is faster to send many primitives to OpenGL in one go, rather than
one at a time. There are several ways of doing this, but one of the easiest ways is to use
display lists
You can think of a display list as a number of OpenGL function calls that have been recorded and can
be played back at top speed. To create a display list, first call

eating a Display List
3D objects are a collection of primitives, typically either triangles or quads, which form part of a larger shape.
For instance, a cube can be created with six quads, one for each side. More complex shapes, particularly
organic shapes like people or bug-eyed aliens, take many more primitives to create. The most efficient way
to store a model is to keep a list of vertices, and additional information about which points to use to draw the
faces (primitives). For instance, a cube could be stored as six vertices (one for each corner), and the faces
would be stored as four indexes into that list (see Figure
This is typically how models are stored in files produced by 3D editing software. Although there are a
XPLOR
I
NG THE
T
H
I
R
D
D
IM
ENS
I
190
Seeing OpenGL in Action
Figure 9-9.
aces and vertices
D
191
It may seem a little odd, but when you move a camera about in a 3D world, you are actually
Listing 9-8.
Flying Around Cube World! (firstopengl.py)
Figure 9-10.
Cube world
D
192
D
193
D
194
D
195
XPLOR
I
NG THE
T
H
I
R
D
D
IM
ENS
I
196
Summary
We’ve covered a lot of ground with this chapter. We started out with matrices, which are an important topic
because they are used everywhere in 3D games, including handhelds and consoles. The math for working
with matrices can be intimidating, but if you use a prebuilt matrix class, such as
197
Sound is an essential component of any game as it gives instant
feedback
from the virtual world. If you were
to play a game with the audio turned down, you would likely find it a very passive experience because we
expect events to be accompanied by sound.
Like other aspects of creating a game, good sound effects require a lot of creativity. Selecting an
HINGS
G
O BOO
M
198
Early computer games used chips that created simple tones to produce electronic bleeps and whistles, but
were incapable of producing complex sounds. These days, gaming hardware can store and reproduce real-
life sounds to create a rich extra dimension to the gameplay. The sound card on your computer can both
record and play high-quality audio.
Sound can be represented as a
wave
. Figure
shows a sound wave that represents a brief portion of a
sound (a fraction of a second)—a full sound would be much longer and more complex. The wave shows how
the energy, or
amplitude
, of the sounds varies over time.
Sound waves form a number of peaks and troughs; the greater the difference in the amplitude of these peaks
and troughs, the greater the
volume
Figure 10-1.
ound wave
Figure 10-2.
ample sound wave
To store a sound on a computer, you must first convert it to digital form, which you can do using a
microphone plugged in to the
mic
199
Sample rates are measured in hertz (Hz), which means samples per second, or kilohertz (KHz), which
means thousands of samples per second. Phone quality is about 6KHz and CD quality is 44KHz. Samples
rates can go higher than CD quality, but only dogs and bats will be able to tell the difference!
Sound Formats
Like images, there are a number of different file formats for digital audio that affect the quality and file size.
Pygame supports two audio formats for sound effects: WAV (uncompressed only) and Ogg. Most, if not all,
software that deals with sound can read and write WAV files. Support for Ogg is not quite as universal but is
still very common. If an application doesn’t support Ogg directly, it may be possible to add it via an upgrade
There are a number of attributes for sound that can affect the quality and file size:
Sample format—
The size of a single sample, which is typically either 8-bit or 16-bit
integers, although some formats do support float samples. Generally you should use
16-bit when storing sound files, because it can reproduce CD-quality sound and is
best supported by sound cards.
Sample rate—
The number of samples stored per second. The most common values
for sample rate are 11025Hz, 22050Hz, or 44100Hz, but there are a number of other
HINGS
G
O BOO
M
200
Creating Sound Effects
One way to create sound effects is to simply record your own. For instance, if you need an engine noise, the
best way to create it is to record the sound of a real engine running. Other sounds are impractical or even
impossible to capture, and a little creativity may be required to create an approximation—a good gunshot
sound can be created by recording a balloon bursting and then using sound-editing software to extend and
deepen the sound. Even phaser fire can be created by recording the sound of a pencil striking the grill of a
p
I
f you want to record sounds outside, and don’t want to drag a laptop around with you, buy a cheap
Dictaphone.
he quality may suffer a little because you are not recording straight to high-quality digital, but you
can always clean up the sound with
udacity (
201
To record sound with Audacity, click the record button (the red circle) to start recording, and then
click the stop button (the yellow square) to finish. The waveform of the sound is then displayed in the main
window, which has a number of controls that you can use to examine the wave and select portions of it.
Figure 10-3.
Audacity
HINGS
G
O BOO
M
202
Echo—
Adds an echo to the sound. Adding Echo can make your effects sound like
they are in anything from an empty room to an enormous cave.
Noise Removal—
If you are not lucky enough to have access to a sound studio and
professional equipment, your recordings may have a slight hissing noise, which is a
result of background noise and imperfections in the microphone and sound card.
The Noise Removal effect does a good job of
cleaning up
your sounds.
Caution

R
203
HINGS
G
O BOO
M
204
Sound Channels

unction That Calculates Stereo Panning
left_volume = 1.0 - right_volume

HINGS
G
O BOO
M
205
Listing 10-2.
sing the stereo_pan Function
p
I
f you update the stereo panning every frame for a moving sprite, it will enhance the stereo effect.
Generally it is best to leave the task of selecting a channel to Pygame, but it is possible to force a
object to play through a particular channel by calling the

eserving Channels
Figure 10-4.
HINGS
G
O BOO
M
206
Here’s how you would force a sound to be played through one of the reserved channels:
See Table

HINGS
G
O BOO
M
207
Hearing the Mixer in Action

ixer in Action (bouncesound.py)
able 10-3.

unctions in pygame.mixer
Creates a Channel object for a given channel index.
Gradually reduces the volume of all channels to 0. Takes the fade time
(in milliseconds).
208
209
210
211
When the
Figure 10-5.
bouncesound.py
HINGS
G
O BOO
M
212
Obtaining Music
If you are not lucky enough to be blessed with musical talent, you may have to use music that someone
else has created. There are a number of stock music websites where you can purchase music files for use in
games or download them for free. You can find a selection of both commercial and free music sites on the
Pygame wiki (
Caution

I
t may be tempting to select a few tracks from your music collection and have your favorite band
as the soundtrack for your game, but this breaks copyright laws and should be avoided!
Playing Music
The
module can play MP3 and Ogg music files. The MP3 support varies from platform
to platform, so it is probably best to use the Ogg format, which is well supported across platforms. You can
convert MP3 to Ogg with Audacity or another sound-editing application.
To play a music file, first call the
function with the filename of the music
track you want to play, and then call
to begin the playback (see Listing
Everything you may want to do with the module can be done with the
module (there
object because only a single music file can be streamed at once). There are functions to stop,

laying a Music File
HINGS
G
O BOO
M
213
Hearing Music in Action

he pygame.mixer.music Functions
Purpose
214
Listing 10-6.
A Pygame Jukebox (jukebox.py)
215
216
217
HINGS
G
O BOO
M
218
The jukebox uses the
Figure 10-6.
he jukebox script
219
Lights, Camera, Action!
In Chapters
, you learned how to manipulate 3D information and use OpenGL to display simple
models. In this chapter we will cover how to work with images to create more visually appealing scenes.
We will also discuss how to read a 3D model from a file, which is an important step in creating a polished game.
Working with Textures
In Chapter
you learned how to create a 3D model from shaded polygons, but in order to make an object
look really convincing you need to use
textures

alculating the Next Power of 2
Note

phics cards do have the capability to use textures that aren’t a power of 2, but it is best to
stick to power of 2 for maximum compatibility.
The upper limit for the size of textures varies across graphics cards. You can ask OpenGL for the
maximum supported texture size by calling
, CAMERA,
220
The following list outlines the steps required to upload image data and create a texture in OpenGL:
Load the image with
Use the
, CAMERA,
221

, CAMERA,
Once the texture has been uploaded, the original Pygame surface object is no longer needed because
Figure 11-1.
exture coordinates
Texture coordinates can be stored in the same way that you would store a two-dimensional vector:
either a tuple or a
object. Components of a texture coordinate are called s and t in OpenGL, but you
can still use a
object for convenience and refer to the components as x and y. Generally, though,
you rarely have to do anything with texture coordinates other than store them and send them to OpenGL as
needed, so a tuple is usually the best choice.
Note

s, tools, and books refer to texture coordinates as u and v, rather than s and t.
, CAMERA,
223
Rendering Textures
To use a texture when rendering a polygon, or any other OpenGL primitive, you must supply a texture
coordinate for each vertex with the
, CAMERA,
224
Listing 11-2.
Textures in Action (opengltex.py)
, CAMERA,
225
, CAMERA,
226
function performs the five steps required to read in the
image and upload the
image data to OpenGL. It then draws a textured quad by sending OpenGL four texture coordinates and four
vertices. Texture coordinates are sent with the
function, which takes the
components
Figure 11-2.
opengltex.py
, CAMERA,
227
Mip Mapping
When there are fewer pixels in a polygon than there are pixels from the texture it is drawn with, OpenGL
has to
skip
some of the pixels from the texture in order to make it fit. This can result in a distortion effect in
the rendered polygon, an effect that worsens the more the texture is scaled down. This distortion can be
distracting in an animated 3D scene and reduces the overall quality of the visuals.
Mip mapping
is a technique to minimize this effect. It works by precalculating progressively smaller
versions of the texture, each with half the dimensions of the previous texture (see Figure
). For instance,
a texture with 256 x 256 pixels will also have a 128 x128-pixel version followed by a 64 x64-pixel version, and
further smaller versions of the texture where each is half the size of the texture preceding it, down to the
final texture (which is a single pixel that is an average of all the pixels in the original). When OpenGL renders
a polygon with a mip mapped texture, it will use the
mip level
that is closest to the size of the polygon on
screen, which reduces the number of skipped pixels and improves visual quality.
Note

M
ip is an acronym for
multum in parvo
, which is Latin for “much in a small space.”
You can upload image data for each
mip level
Figure 11-3.
ip maps
, CAMERA,
228
(which are not needed). For example, the following call can replace the call to
Listing
(See 11-2.1.py in the source code documents for full example):
The only downside of using mip mapped textures is that they use a third more video memory than
non–mip mapped textures, but the improvement in visual quality is well worth it. I recommend using mip
mapping for all textures used in 3D scenes. You won’t need to use mip maps for textures that aren’t scaled,
such as fonts or the heads-up display.
, CAMERA,
229
Texture Wrapping
A texture coordinate with components in the zero to one range will refer to a point inside the texture, but it is
not an error to have a texture coordinate with components outside that range—in fact, it can be very useful.
How OpenGL treats coordinates that are not in the zero to one range is defined by the
ou run the edited Listing

, CAMERA,
230
Repeating textures has the same effect as transforming the components of every texture coordinate
with the following Python function (although the wrapping is done by your graphics card and not Python).
The
p
t have been designed to be seamless—that is, if you place them
Figure 11-4.
epeating texture coordinates
, CAMERA,
231
Now when you run Listing
you should see that the repeated images are mirrored around the s and
, CAMERA,
232
Files for storing 3D information will contain at least a list of vertices, and will probably also contain a
list of texture coordinates and normals. Many also contain additional information regarding textures and
lighting. You don’t have to use all the information in a 3D model, but the more features of the format you
implement, the more closely it will resemble the model that was created by the artist.
p
M
any game developers publish the 3D model format used in their games. You may be able to test your
game with characters taken from a commercial game—but be careful about breaking copyright laws!
OBJ Format for 3D Models
To work with 3D models we are going to use the Wavefront OBJ format (extension
), which is a simple
text format that has been in existence for many years. Most software that works with 3D models will be able
to at least write OBJ files, and probably read them as well. They are text based, so you can open them in a text
editor such as Windows Notepad, or the equivalent on other platforms.
OBJ files often come with a material library file (with the extension
), which contains various
, CAMERA,
233
Material Library Files
Wavefront OBJ files are often partnered with a material library file that contains the texture and lighting
information. When you encounter a
command in the OBJ file, it introduces a material library file
that contains this extra information. The filename of the material library is given in the first word of the
command data, and should be appended with the extension
Material libraries are also text files, and can be parsed in the same way as the parent OBJ file. In the
material library file, the

ines in a Wavefront OBJ File
Indicates the line is a comment and should be ignored by the software.
, CAMERA,
The class we are building is called
and is responsible for reading the model and storing its

nformation Stored in the Model3D Class
A list of vertices (3D points), stored as tuples of three values (for x, y, and z).
A list of texture coordinates, stored as tuples of two values (for s and t).
A list of normals, stored as tuples of three values (for x, y, and z).
A dictionary of
objects, so we can look up the texture filename given
the name of the material.
A list of
objects that will store the faces for each material.
A display list
that we will use to speed up OpenGL rendering.
Figure 11-5.
uturistic tank object in AC3D
, CAMERA,
235
In addition to the
class, we need to define a class to store materials and
face groups
, which are
polygons that share the same material. Listing
is the beginning of the
class.
Listing 11-3.

lass Definitions in model3d.py
N

file_in = open(fname)
, CAMERA,
236
, CAMERA,
237
glBindTexture(GL_TEXTURE_2D, material.texture_id)
Note

or simplicity, the
M
odel3D class only works with
O
BJ files that contain triangles.
I
contains quads or other polygons, you will need to convert it to triangles with your 3D modeler.
, CAMERA,
238
Listing 11-5.
arsing the Material Library
for line in file_mtllib:
These two functions (
) are enough to read all the information we need from

tex_coords = self.tex_coords

, CAMERA,
239

leaning Up OpenGL Resources
self.free_resources()


Note

I
function, because it may cause errors if
ython cleans up your
M
odel3D object after
P
y
O
pen
G
L has quit.
, CAMERA,
Using the Model3D Class

endering the Tank Model (tankdemo.py)
from OpenGL.GLU import *
, CAMERA,
241
function in Listing
, CAMERA,
242
The call to
creates a rotation matrix of 15 degrees around the x axis, which is
the equivalent of looking down a little. This rotation matrix is multiplied by a translation matrix, with a call to
, which effectively moves the tank down by 1.5 units and back by 3.5 units.
The second call to
makes the tank rotate about the y axis so we can see it in motion.
When you run Listing
, you should see a formidable-looking tank rotating about the y axis (see
Figure
Figure 11-6.
tankdemo.py
Note

N
ot all 3D modeler applications use the same scale.
I
f you find that your model is extremely large or
very small, you may have to scale it before exporting, or change the code to view the object at a different distance.
, CAMERA,
243
Summary
Textures are the primary way of making a 3D scene look convincing because you can apply images of the
real world to objects in your game. Photographs are a great way of creating textures—a digital camera
is a fantastic tool for game development! Or you can use images from other sources; the Pygame wiki
) has a great collection of links to sites with free textures.
Because OpenGL was created independently of Pygame, there is no one function that you can use to
245
ENE WITH OPEN

ENE WITH OPEN
247
The ambient is a dark gray because we want the effect to be localized and not contribute much light
outside of a short distance. The diffuse is a bright flame red, and the specular is intense white to cause
brilliant highlights in nearby surfaces.
Lights also have three
attenuation
factors, which define how the brightness of a point light source
changes over distance. The three factors,
constant
linear,
quadratic,
are used by OpenGL to calculate
a single number that is multiplied by the colors produced by the lighting calculations. The formula that
OpenGL uses is equivalent to the

unction That Calculates the Attenuation Factor
Note

he maximum brightness level that Open
G
L can use is 1.0—values greater than 1.0 will not have
any additional effect.
For a fireball effect, we would probably want to make the emitted light intense in the immediate area
surrounding the visual effect but fade away quickly. The following calls to
Note

ttenuation requires Open
G
L to do a little more work for each polygon rendered and can have a
performance impact on your game—although it probably won’t be noticeable unless you have an old graphics
card. Our game here has very few polygons relative to what modern games put out, so it definitely should not
Working with Materials
material
ENE WITH OPEN
249

lend Factor Constants
Blend Factor ConstantExplanation
Multiplies by zero
Multiplies by one
Multiplies by source
Multiplies by one minus the source color
Multiplies by destination
Multiplies by one minus the destination color
Multiplies by the source alpha component
Multiplies by the inverse of the source alpha component
continued
ENE WITH OPEN
250

lending Equation Constants
Blend Equation ConstantExplanation
Adds the source and destination colors
Subtracts the destination from the source color
Subtracts the
source
from the destination color
Calculates the minimum (darkest) of the source and destination colors
Calculates the maximum (brightest) of the source and destination colors
Combines the source and destination colors with a
logic operation
(see the OpenGL documentation for information on logic operations)
Blend Factor ConstantExplanation
Multiplies by the destination alpha
Multiplies by the inverse of the destination alpha

continued
Another OpenGL function involved in blending is
ENE WITH OPEN
251
Alpha Blending
One of the most commonly used blending effects is alpha blending, which uses the alpha channel in
an image to control the opacity of the pixels. Alpha blending can be used to create texture with holes or
irregular edges, such as a torn flag.

ython Alpha Blend Function
ENE WITH OPEN
252
Listing 12-3.
ython Additive Blend Function
The reverse of additive blending is
subtractive
blending, where the source color is subtracted from the
blending:
rather than
because we
want to subtract the source from the destination and not the other way around.
There is no reverse version of
because A+B is always the same as B+A (the same is not true for
subtraction; A–B is not always the same as B–A).
Subtractive blending is great for rendering smoke because several layers result in solid black. The
function in Listing
is the Python equivalent of subtractive blending.
Listing 12-4.

ython Subtractive Blend Function
Listing 12-5.

emonstrating Blending Effects (blenddemo.py)

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
Figure 12-1.
Blending effects
Try changing the constants in the
to produce some more interesting
effects. If there is a particular effect you want to implement that isn’t covered here, you will likely be able to
come into range of the camera.
Fog is also useful for creating visual effects in its own right; the most obvious use is to simulate real fog,
but you can also use the feature to enhance a gloomy indoor scene by fogging to black or to simulate red
haze on Mars.
ENE WITH OPEN
257
The
Figure 12-2.
A heavily fogged tank
ENE WITH OPEN
259
Rendering the Backdrop
Note

You may have to
the normals on the faces of the cube, which makes them point inward rather
than outward.
he reason for this is that the cube will be viewed from the inside rather than the outside, and
Generating the skybox textures may require a little more effort because each texture must seamlessly
align with the four other textures it shares an edge with. If you are artistically inclined, you can draw or
paint these textures, but it is probably easier to use 3D modeling software to render six views of a scene for
each face of the skybox. An excellent choice for rendering skyboxes is Terragen (
Figure 12-3.
The texture of a skybox
ENE WITH OPEN
261
Disable lighting with
. We don’t need to use OpenGL’s
lighting features because the textures of the skybox have effectively been prelit. With
lighting disabled, OpenGL will render the textures with the original brightness levels.
Disable the depth buffer with
. Normally if the player was inside
a cube he would not be able to see anything outside of the cube, which is obviously

endering a Skybox (skybox.py)
from OpenGL.GLU import *
ENE WITH OPEN
264
Where to Go for Help
One of the joys of games programming is that it offers up many interesting problems that give a real sense
265
This appendix documents some of the most fundamental classes in the Game Objects library that
provide a toolbox for creating 2D and 3D games. For up-to-date information regarding Game Objects,
see
The Game Objects library consists of a number of submodules that can be imported separately. Generally it
is best to import only the classes you need using the
syntax. For example,
this line imports the
class:
Occasionally there are helper functions from the submodules that you may also want to use. In this case
you can use
to import everything into your namespace. For example, the following
line will import everything in the
class:
The Game Objects library is an open source project, which means that any programmer may contribute. You are
encouraged to submit any bug fixes you find, or classes that you think may be useful additions to the library.
gameobjects.color.Color
Color objects represent a color with an alpha value. The components are stored in the range zero to one, as
used by OpenGL, but you can convert to integer RGBA format with the
attribute or
multiply or divide colors by a scalar value (e.g., an integer or float), but adding or subtracting a scalar will
throw a
exception.

A
ME OBJECT REFE
R
266
Constructor
The
constructor takes the red, green, and blue components and an optional alpha
component, in the range zero to one. The components can also be given as a sequence of three or four

ameobjects.color Attributes
Red component in the zero to one range
Green component in the zero to one range
Blue component in the zero to one range
Alpha component in the zero to one range
rgba8
Tuple of (red, green, blue, alpha) components, in the 0 to 255 range (compatible
with Pygame’s draw functions)
rgb8
Tuple of (red, green, blue) components, in the 0 to 255 range
Table A-2.


A
ME OBJECT REFE
R
267
Table A-3.

ameobjects.matrix44.Matrix44 Attributes
AttributeExplanation
The x axis of the matrix
Alias for the x axis
The y axis of the matrix
Alias for the y axis
The z axis of the matrix
Alias for the z axis
The translation part of the matrix

A
ME OBJECT REFE
R
268

atrix44 Attributes

A
ME OBJECT REFE
R
269


ector2 Attributes
AttributeExplanation
The x component of the vector.
The y component of the vector.

A
ME OBJECT REFE
R
270
Table A-8.


A
ME OBJECT REFE
R
271

ector2 Attributes
AttributeExplanation
The x component of the vector.
The y component of the vector.
The z component of the vector.


273
Packaging Your Game
If you have gone to the effort of writing a game with Pygame, you will likely want to share your masterpiece
with others. The simplest way to distribute your game is to bundle your Python code and data as a
compressed archive file, such as ZIP, TAR, or GZIP, and upload it to your website or send it via e-mail. The
problem with this approach is that Python and any external modules you use must be installed before
your game can be played, which makes code distributions suitable only for other Python programmers. To
distribute your game to a wider, nontechnical audience, you will need to package your game in a familiar
way for your chosen platform(s).
This appendix covers how to package your game into a format that allows nontechnical users to install
and play it.
Creating Windows Packages
Installing a game on Windows generally involves double-clicking an EXE file, which launches an installer
application. The installer is typically in the form of a
wizard
with several pages that display the license
agreement and ask the user where to copy the game files and what icons to install. A Finish button on the
final page begins copying the files and creating icons.
There are two steps required to create a user-friendly installer for your Pygame game on the
Windows platform:
Turn your main Python file into an executable that runs without Python installed.
Use installer builder software to create a single EXE file that contains your
game’s files.
Creating the installer makes your game accessible to the widest audience, and is essential if your game
is intended to be commercial. You can skip the second step if your intended audience is technical enough to
decompress a ZIP file and double-click an EXE file.
Using cx_Freeze
To turn a Python file into an executable file, you can use
, which is itself a Python module.
isn’t part of Python’s standard library, but it can easily be installed with the following command
in cmd.exe / bash / terminal:
PA
GING YOUR
274
Before creating an executable for your Python code, you need to write

irst we’re importing
, then we specify what we’re going to be creating an executable out
PA
GING YOUR
275
This creates a dist directory. Inside dist is the installer. Now you can distribute just this installer to your
friends, and then they can install it. Keep in mind that if you have a 32-bit version of Windows, this makes a
32-bit installer for the game. 32-or 64-bit Windows can install and run this. If you are operating with a 64-bit
version of windows, your distribution will be 64-bit, and will not be runnable by 32-bit machines.
Creating Packages for Linux
Creating packages for Linux is easier than for Windows, because most distributions come with Python
installed by default and package managers can download the required version of Python, if it is not
present. To create a Linux package, use the
module in the Python standard library, which can
produce source archives (tarballs) or RPM files. It is also a good idea to include a description of the game’s
requirements, just in case the Linux distribution is unable to provide them.
For more information on the
module, see the documentation online at
. You can also use
with Linux, by installing it with
Then, you can create a distribution of your game with:
Creating Packages for the Mac
You can also create Mac disk images with
. You need to install
with
See Listing
in the Windows section for creating the
277
Aliasing,
Antialiasing,
Articial intelligence (AI),
exploring/seeking states,
opponents creation,
pseudocode
imp’s brain,
platform monster,
state machine,
Audacity,
AZERTY and Dvorak,
Bilinear ltering,
Bit block transfer,
Blending,
additive blending,
alpha blending,
blend factor constants,
equation constants,
glBlendColor function,
glBlendFunc function,
potential problems,
subtractive blending,
D
Color addition,
Color subtraction,
Concatenation,
Escape character,
Field of view (FOV),
Fog
Game input devices
joysticks and joypads (
see
Joysticks and
joypads)
keyboards (
see
Keyboards)
mouse (
see
Mouse)
Game Objects
contribute,
import,
gameobjects.color.Color,
attributes,
278
Hardware surface,
Joystick and joypads,
demo script,
direction controls,
analog sticks,
dead zones,
d-pads,
events,
joystick objects,
pygame.joystick module,
shoulder buttons,
JPEG (Joint Photographic Expert Group) image
le,
Keyboards
AZERTY and Dvorak,
directional movement,
directions,
Lightning
attenuation factors,
directional lights,
Mac package,
Matrix
assert keyword,
components,
3D transformations,
forward vector,
Matrix44 class,
multiplication,
right vector,
rotation matrix,
scale matrix,
transformations,
translation matrix,
types,
up vector,
Mip mapping,
Mouse,
gameplay,
pygame.mouse functions,
rotational movement,
Move objects
diagonal movement,
frame rate,
straight-line movement,
frame rate and speed comparison,
tick function,
time-based movement,
vectors,
creation,
diagonal movement,
Game objects,
magnitude,
multiplication and division,
negation,
NumPy,
subtraction,
time-based movement,
unit vectors,
Negative indexing,
Non-player characters (NPCs),
NumPy,
Object-oriented programming (OOP)
class
279
properties,
purpose
cube world,
display lists,
faces and vertices,
fog
Packages
Linux,
Mac,
Windows
installer,
using cx_Freeze,
Parallel projection,
Perspective projection,
Picture element,
Pixel,
Playing music, Pygame,
jukebox script,
pygame.mixer.music functions,
web sites,
280
if statement,
not operator,
or operator,
loops,
for,
while,
math module,
in OOP,
practical use,
print function,
random module,
scripts,
standard library,
import keyword,
strings
concatenation,
escape character,
QWERTY keyboards,
Rotation matrix,
Scale matrix,
Simple DirectMedia Layer (SDL),
Skyboxes,
creation,
enhancements,
rendering,
textures,
Skydome,
Sound
amplitude,
description,
eects
amplify,
Audacity,
change pitch,
echo,
noise removal,
recording,
web sites,
formats,
glass smashing,
mues,
pitches,
Pygame
audio streaming (
see
Playing music,
Pygame)
ball bounce eects,
buer,
functions,
mixer functions,
size,
sound channels,
sound objects,
stereo,
sample rates,
sound wave,
storing sounds,
Sounddogs,
State machines
Ant entity class,
AI simulation,
check_conditions function,
exploring state,
seeking state,
entities,
entry actions and exit actions,
game entities
base class,
process function,
render function,
links,
seeking and exploring state,
World class,
281
T
Unit vector,
Visuals
colors
blending,
color subtraction,
in Pygame,
scaling,
draw functions
pygame.draw.aaline,
pygame.draw.aalines,
pygame.draw.arc,
pygame.draw.circle,
pygame.draw.ellipse,
pygame.draw.line,
pygame.draw.lines,
pygame.draw module,
pygame.draw.polygon,
pygame.draw.rect,
images
alpha channel,
storing image
formats,
translucency,
pixel power,
surface objects
blitting,
clipping,
convert and convert_alpha
, X, Y, Z
Windows packages
installer,
using cx_Freeze,
Beginning Python Games
Beginning Python Games Development
Copyright © 2015 by Harrison Kinsley and Will McGugan
obtained through RightsLink at the Copyright Clearance Center. Violations are liable to prosecution under
the respective Copyright Law.
ISBN-13 (pbk): 978-1-4842-0971-4
ISBN-13 (electronic): 978-1-4842-0970-7
Trademarked names, logos, and images may appear in this book. Rather than use a trademark symbol
with every occurrence of a trademarked name, logo, or image we use the names, logos, and images only
in an editorial fashion and to the benefit of the trademark owner, with no intention of infringement of the
trademark.
The use in this publication of trade names, trademarks, service marks, and similar terms, even if they are
is book is dedicated to open source.
vii
echnical Reviewer

Introduction

............................................................................................................
xxi
Chapter 1: Intr
oducing Python

Your First Look at Python

.................................................................................................
1
2
Strings

Lists and Tuples

Unpacking

.............................................................................................................................................
13
Loops

Python in Practice
16
Summar
y

........................................................................................................................
17
Chapter 2: Exploring Python

Creating Scripts

Working with Logic

.........................................................................................................
20
20
if Statement

and Operator

Or Operator

Not Operator

.........................................................................................................................................
22
else Statement

.....................................................................................................................................
23
elif Statement

.......................................................................................................................................
23
viii
24
24
Default V
alues

Introducing Object-Oriented Programming
26
26
Cr
eating an Object

................................................................................................................................
27
Adding to our Class
Python in Practice
d Library

.............................................................................................
33
33
Useful Modules for Games

....................................................................................................................
34
Math Module

Summary
37
Chapter 3: Intr
oducing Pygame

History of Pygame

..........................................................................................................
39
Installing Pygame

...........................................................................................................
40
Using Pygame

Hello World Revisited
.....................................................................................................
42
Understanding Events

....................................................................................................
47
47
Handling Mouse Motion Events

...........................................................................................................
50
Handling Mouse Button Events

Handling Keyboard Events

....................................................................................................................
50
Filtering Events

.....................................................................................................................................
52
Posting Events

......................................................................................................................................
53
Full-Screen Displays
ws with No Borders

....................................................................................................................
56
Additional Display Flags

......................................................................................................................
57
57
Pygame
in Action

Summary

........................................................................................................................
60
Chapter 4: Cr
eating Visuals

Using Pixel Power

Working with Color

Representing Color in Pygame
62
Scaling Colors

.......................................................................................................................................
64
Blending Colors

....................................................................................................................................
66
Creating Images with an Alpha Channel
68
Storing Images

Working with Surface Objects
Creating Surfaces
69
Filling Surfaces

.....................................................................................................................................
71
...................................................................................................................
72
Blitting

Drawing with Pygame
pygame
draw
rect

pygame
draw
polygon

pygame
draw
circle

pygame
draw
ellipse

pygame
draw
arc

pygame
draw
line

pygame
draw
lines

pygame
draw
aaline
pygame
draw
aalines

Summary
80
ve

Understanding Frame Rate
Moving in a Straight Line

It’s About Time
85
Diagonal Mo
vement

Exploring Vectors
Creating Vectors
90
Storing V
ectors

Vector Magnitude

Unit Vectors

Vector Addition

Vector Subtraction

Vector Negation

Vector Multiplication and Division

Using Vectors to Create Movement
Diagonal Movement
Vector Class

Summary
101
Chapter 6: Accepting User Input

........................................................................
103
Controlling the Game

Understanding Keyboard Control
.................................................................................
104
ectional Movement with Keys

Rotational Movement with Keys

.........................................................................................................
110
Rotational Movement with the Mouse
113
Mouse Gameplay

................................................................................................................................
116
Implementing Joystick Control
Joystick Basics
ystick Buttons

Joystick Direction Controls

Joystick Objects

Seeing Joysticks in Action
124
Summar
y

......................................................................................................................
127
ake Me to Your Leader

Creating Ar


.....................................................................
129
130
Exploring AI

Implementing State Machines
.....................................................................................
131
132
Building W
orlds

...................................................................................................................................
133
Ant Entity Class

Building the Brains

Summary
151
ving into the Third Dimension

Creating the Illusion of Depth

.......................................................................................
153
Understanding 3D Space

Using 3D Vectors
ime-Based Movement in 3D

.............................................................................................................
158
Parallel Projections
159
Perspective Projections

Field of View

A 3D World
163
Summar
y

......................................................................................................................
167
xii
Chapter 9: Exploring the Thir
d Dimension

.........................................................
169
What Is a Matrix?

.........................................................................................................
169
170
Matrix Components

Translation Matrix

...............................................................................................................................
173
Scale Matrix

........................................................................................................................................
174
Rotation Matrix

...................................................................................................................................
175
Matrix Multiplication

Matrices in Action
177
Introducing OpenGL

......................................................................................................
182
183
Initializing OpenGL

..............................................................................................................................
183
OpenGL Primer

Seeing OpenGL in Action
190
Summar
y

......................................................................................................................
196
Chapter 10: Making Things Go Boom

................................................................
197
What Is Sound?

............................................................................................................
197
Storing Sound

Sound Formats
Creating Sound Effects
200
Stoc
k Sound Effects

.....................................................................................................
202
Playing Sounds with Pygame

.......................................................................................
202
203
Sound Channels

..................................................................................................................................
204
Mixer Functions

Hearing the Mixer in Action

................................................................................................................
207
xiii
211
212
Playing Music

Hearing Music in Action

Summary
218
Camera, Action!

Working with Textures

Uploading Textures with OpenGL
exture Coordinates

Rendering Textures

.............................................................................................................................
223

Seeing Textures in Action

...................................................................................................................
223
Mip Mapping

.......................................................................................................................................
227

............................................................................................................................
228
Min and Max Filters

Texture Wrapping

Working with Models
231
231
OBJ For
mat for 3D Models

.................................................................................................................
232
Parsing OBJ Files

Material Library Files

Seeing Models in Action

.....................................................................................................................
233
Using the Model3D Class

Summary
243
xiv

......................................................
245
Understanding Lighting

................................................................................................
245
Enabling Lighting

..........................................................................................................
245
246
W
orking with Materials

.......................................................................................................................
247

.........................................................................................................................
248
Managing Lights

.................................................................................................................................
248
249
249
Alpha Blending

...................................................................................................................................
251
Additive Blending

Subtractive Blending

Seeing Blending in Action

...................................................................................................................
252
Blending Issues

..................................................................................................................................
256
256
256
Seeing Fog in
Action

Rendering the Backdrop
Skyboxes
yboxes in Action
Skybox Enhancements

Where to Go for Help
264
Summar
y

......................................................................................................................
264
Appendix A: Game Object Refer
ence

.................................................................
265
Importing

......................................................................................................................
265
Contributing

..................................................................................................................
265
gameobjects
.
color
Color

...............................................................................................
265
266
Attributes

............................................................................................................................................
266

..............................................................................................................................................
266

....................................................................................................................................
267
267
267
Attributes

............................................................................................................................................
267

..............................................................................................................................................
268

....................................................................................................................................
269
Vector2
269
269
Attributes

............................................................................................................................................
269

..............................................................................................................................................
270

....................................................................................................................................
270
Vector3
270
270
Attributes

............................................................................................................................................
271

..............................................................................................................................................
271

....................................................................................................................................
271
ackaging Your Game

Creating Windows Packages

Using cx_Freeze
273
Building the Installer
Creating Packages for Linux
eating Packages for the Mac

....................................................................................
275
Index

.....................................................................................................................
277
xvii
About the Authors
Harrison Kinsley
is a software developer and entrepreneur living
in Texas. He has multiple businesses, all built with Python.
xix
About the Technical Reviewer
Michael Thomas
has worked in software development for more than
20 years as an individual contributor, team lead, program manager,
and vice president of engineering. Michael has more than 10 years of
experience working with mobile devices. His current focus is in the
medical sector, using mobile devices to accelerate information transfer

Приложенные файлы

  • pdf 11181159
    Размер файла: 5 MB Загрузок: 0

Добавить комментарий