Archive for the ‘Game Objects’ Category

Table of Contents for Pygame Book

Sunday, October 7th, 2007

The following is a list of the chapter titles for Beginning Game Development with Python and Pygame, and a brief explanation of the contents.

Any questions about the book contents, let me know!

Chapters:

  1. Introducing Python
    Introduction to basic Python.
  2. Exploring Python
    Goes a little deeper in to Python, covers Classes.
  3. Introducing Pygame
    Explains how import and use Pygame.
  4. Creating Visuals
    Covers different ways of drawing to the screen.
  5. Making Things Move
    Explains animation, vectors and time-based movement.
  6. Accepting User Input
    Covers how to read input devices and connect them to in-game motion.
  7. Take Me to Your Leader
    Covers artificial intelligence.
  8. Moving into the Third Dimension
    Explains the basic 3D concepts, with samples.
  9. Exploring the Third Dimension
    Covers 3D maths and introduces OpenGL.
  10. Making Things Go Boom
    Sound and Music.
  11. Lights, Camera, Action!
    Covers textures and reading 3D models from files.
  12. Setting the Scene with OpenGL
    Covers lighting, blending, fog and other OpenGL features.

Appendices:

  • A. GameObjects Reference
  • B. How to package Pygame games

Free chapter of Beginning Game Development with Python and Pygame

Thursday, October 4th, 2007

My book, Beginning Game Development with Python and Pygame, is finally finished! It was a labor of love, and a lot of work. Apress have graciously allowed me to give away a free chapter.

I chose chapter 7, which is on the subject of Artificial Intelligence. I selected this chapter because it is nicely self-contained and doesn’t require much additional understanding of other game concepts. It is an unusual chapter, in that it contains the largest listing in the book. I tried to avoid really long listings, but in this case I think it was justified so that the code in the book actually runs; I hate leaving any code as an exercise for the reader.

Pdf Icon
Download Chapter 7, Take me to Your Leader

Chapter 7 discusses how to build a simple AI simulation of an ants nest using a state machine, a technique which can be applied to virtually any simulation that you might want in a game. You can download the code for the book below, it isn’t interactive, but I think it is entertaining to watch for a minute or two!

Download Ant Simulation

The ant simulation uses the gameobjects library, which you can install with the following comand:

easy_install gameobjects

The book will be available in all good book shops, and some bad ones, on October 24th. Thanks to everyone at Apress for guiding me through the writing process!

Update: I blogged the Table of Contents

In yr code twiddling yr bits

Saturday, June 30th, 2007

Added a few functions to gameobjects.util that seemed worth sharing. The first two are two-dimensional versions of range and xrange. When iterating over something 2 dimensional (such as pixels in an image) you typically have an outer loop for the y coordinate, and an inner loop for the x coordinate. The range2d and xrange2d functions combine these two loops in to one and take range iterables as parameters.

def range2d(range_x, range_y):
 
    """Creates a 2D range."""
 
    range_x = list(range_x)
    return [ (x, y) for y in range_y for x in range_x ]
 
def xrange2d(range_x, range_y):
 
    """Iterates over a 2D range."""
 
    range_x = list(range_x)
    for y in range_y:
        for x in range_x:
            yield (x, y)

Here’s how you might use range2d to iterate over the coordinates in an image.

for x, y in range2d(xrange(width), xrange(height)):
    #Do something with x, y

The xrange2d function returns a generator rather than a list, but works the same.

Next up we have two functions to help with power of two textures; is_power_of_2 returns True if a given value is a power of 2, and next_power_of_2 returns a power of 2 that is greater than or equal to a given value. These may be useful if you are working with OpenGL which requires power of 2 textures. I know newer versions of OpenGL support non-power of 2 textures, but it is a good idea to stick to power of 2 dimensions for compatibility.

def is_power_of_2(n)
    """Returns True if a value is a power of 2."""
    return log(n, 2) % 1.0 == 0.0
 
def next_power_of_2(n):
    """Returns the next power of 2 that is greater than or equal to n"""
    return int(2 ** ceil(log(n, 2)))

There is actually bit-twiddling magic that could replace both of these functions, but I don’t want to make any assumptions about which is faster in Python. The bit-twiddling code to calculate the next power of 2 is particularly suspect. It may generate just a dozen or so instructions in C, but I suspect that the Python overhead would make it slower than doing the float math. I may be wrong, but I lack the motivation to do the tests. The following is C *spit* code to find the next power of 2.

unsigned int v; // compute the next highest power of 2 of 32-bit v

v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v++;

If you are going for a job interview in the games industry, memorizing that code may be worthwhile, but you will never need it again!

Ok. Thats your lot. Go play nicely.

Master time with PyGame

Friday, June 15th, 2007

A novice games programmer learns he can move a sprite by adding a constant to its position every frame. For a while he is happy and mocks the master games programmer for having wasted many years learning. But soon the novice realises his sprites are unpredictable and move at different rates on different machines. The novice is despondent and visits the master for advice.

“Master. Why do my sprites not obey my commands? They jump when I ask them to slide.”

“Frame rate is like the wolf, it can not be tamed”, replies the master.

The novice returns to his code and a revelation comes to him. “I must move my sprites with the frame rate!” The novice changes his sprite code to move a distance relative to the time since the previous frame, and his sprites become at one with the frame rate. “I must truly be a master”, thinks the novice.

For a while the novice is happy, and produces many simple games. But as the novice’s logic gets more complex he is faced with a problem. “My game updates are tied to the frame rate!”, thinks the novice. He realises that his game will run differently on other machines and yearns for the simpler days when he thought frame rate was constant. Despondent, he visits the master for advice.

“Master. How can I make my game run predictably on all machines?”

“Time is not rigid as a tree. Time is supple, as a reed”, replies the master.

The novice goes back to his code and ponders the master’s advice. A revelation comes to him, “Game logic can run in it’s own time!” With that thought in mind, he separates his game logic from the render code and soon his game logic runs independently of the frame rate.

The novice is humbled and thanks the master for his help.

“Truly, you are a master now”, replies the master.

To become a master you can either meditate in a cave in Tibet or use the GameClock class in the Game Objects library. GameClock manages game time, which marches on at a perfectly constant frame rate, no matter how many frames you can actually render. The main advantage of this approach is that the game will run the same on a fast computer, as it does a slow computer, which is extremely useful for recording demos or adding network play. It also makes the math for moving sprites (2D or 3D) a little simpler, because you can just add constants each frame.

Here’s a snippet from the example project that shows how to separate the render loop in to an update phase and a render phase. The call to game_clock.update is an iterator that returns the frame count and time for each game logic update. It will return as many updates as necessary for game time to ‘catch up’ with the real time.

        # Update phase
        for frame_count, game_time in game_clock.update():
 
            for ball in balls:
                ball.update()
 
        # Render phase
        for ball in balls:
            ball.render(screen)

The update function calculates the position of the sprite at the current update, and the position it will be at the next update. This is because the render phase will likely occur at some point between game logic updates, and the render position should be adjusted proportionally. The method get_between_time returns a value between 0 and 1 that you can use to interpolate value between two game logic updates.

For example, if the sprite contains its current position (self.position) and its position at the next update (self.next_position), then you could find the render position with the following code (lerp is a function in gameobjects.util).

        x, y = lerp( self.position,
                     self.next_position,
                     game_clock.get_between_frame() )

So what is a good rate for the game logic update? In my experience 20 logic updates per second is about right for most games. You can increase this rate if you want finer control, but it is probably not a good idea to go much lower as it will reduce the responsiveness of the game.

An additional advantage of GameClock is that you can control the speed of time with little effort. If you call game_clock.set_speed(0.5), then half as many game logic updates will be issued and the game will run at half speed. You can also make the game run faster by setting the speed to a value greater than 1.0. Alas, you can’t set the speed to a negative value, as this would violate the laws of the cosmos.

You can experiment with the game logic update rate and time speed with the GameClock sample code. You will need PyGame of course, and Game Objects 0.0.2. Game Objects can be easy installed with the command: easy_install gameojects.

Download GameClock sample code

Here’s a screenshot of the sample code running. I really must try to write samples that don’t feature shiny spheres!

gametimesample

Game Objects Commandments

Thursday, June 7th, 2007

I’ve moved Game Objects to Google Code. It’s new home is http://code.google.com/p/gameobjects/. There are source and Win32 packages available.

Game Objects is intended to be a collection of classes to assist with the creation of games, or other realtime applications. Currently there is a 2D and 3D Vector class, and a well optimized 4×4 Matrix class, but eventually Game Objects will contain code for general route finding, entity management, AI and other cool stuff. I’m happy to take suggestions, and if you would like to submit code - even better! All classes should following these commandments.

  1. Easy to use. Thou shalt be no more complex than absolutely necessary, and thou shalt protect the user from doing stupid things.
  2. Fast. Thou shalt be fast, unless it comes in to conflict with 1.
  3. Pure Python. Thou shalt be in pure Python. Optimized C versions may exist as long as the interface is identical.
  4. Few dependencies. Thou shalt not require external modules, other than the standard library. External modules may be optional if they increase performance.

Current version is 0.0.1, but don’t let the low version scare you, the current classes are quite stable. Most of my previous little PyGame experiments have used old versions of Game Objects, so I have ironed out most of the kinks. I plan on putting together a collection of samples, so there is something to play with. Any suggestions for interesting projects that make use of Game Objects will be gratefully received.

Update: I have created a Google Group for discussion of Game Objects (http://groups.google.com/group/gameobjects).

Game Objects 3D math

Sunday, May 20th, 2007

I’ve just uploaded a new version of Game Objects. The 3D maths classes (Vector2, Vector3 and Matrix44) are reasonably stable now. I’d like to invite Python coders to play around with them, and suggest any improvements. My intention was to make something that was very easy to use, but well optimized. Game Objects is public domain. Do what you want with the code - go crazy!

There is no documentation at the moment I’m afraid, but here are a few edited highlights.

Vector3 class

>>> from gameobjects.vector3 import *
>>> A = (-5, 2, -6 )
>>> B = (10, 2, 8)
>>> AB = Vector3.from_points(A, B)
>>> print AB
(15, 0, 14)
>>> AB.length
20.518284528683193
>>> AB.length = 1
>>> print AB
(0.731055, 0, 0.682318)
>>> AB *= 2
>>> print AB
(1.462111, 0, 1.364637)
>>> AB += (1, 2, 3)
>>> print AB
(2.462111, 2, 4.364637)

Matrix44 Class

>>> from gameobjects.matrix44 import *
>>> identity = Matrix44()
>>> print identity
[ 1 0 0 0 ]
[ 0 1 0 0 ]
[ 0 0 1 0 ]
[ 0 0 0 1 ]
>>> scale = Matrix44.scale(2.)
>>> print scale
[ 2 0 0 0 ]
[ 0 2 0 0 ]
[ 0 0 2 0 ]
[ 0 0 0 1 ]
>>> scale.transform( (1, 2, 3) )
(2.0, 4.0, 6.0)
>>> from math import radians
>>> rotate = Matrix44.x_rotation(radians(45))
>>> print rotate
[ 1         0         0         0 ]
[ 0         0.707107  0.707107  0 ]
[ 0         -0.707107 0.707107  0 ]
[ 0         0         0         1 ]
>>> p = (5, 10, 0)
>>> rotated_p = rotate.transform(p)
>>> print rotated_p
(5.0, 7.0710678118654755, 7.0710678118654746)
>>> inverse_rotate = rotate.get_inverse()
>>> inverse_rotate.transform(rotated_p)
(5.0, 10.0, 0.0)
>>> rotation.right
Traceback (most recent call last):
  File "“, line 1, in ?
NameError: name ‘rotation’ is not defined
>>> rotate.right
(1.0, 0.0, 0.0, 0.0)
>>> rotate.translate
(0.0, 0.0, 0.0, 1.0)
>>> rotate.translate = (10, 2, 5)
>>> print rotate
[ 1         0         0         0 ]
[ 0         0.707107  0.707107  0 ]
[ 0         -0.707107 0.707107  0 ]
[ 10        2         5         1 ]

Close
E-mail It
Socialized through Gregarious 42