Tuesday, July 31, 2007

9 million sprites per second


Well... almost.

I've just clocked my latest GFX lib release rendering 1 million 5x5 alpha blended sprites at 9 frames per second. Larger sprite sizes increase the rendering time, for example a 64x64 sprite can be rendered 6 hundred thousand times per second... but 9 million is a better number for a headline. :-)

This kind of speed comes courtesy of OpenGL batch mode operations, implemented via vertex arrays, which I am using via a Pyrex wrapper. I've re-implemented a tiny sub-set of numpy array functionality, so you can do things like move sprites around by adding an array of velocities to the sprite vertices... which is useful when implementing particle systems for example.

I imagine it will also be useful for rendering large tilemaps, game levels etc. Stay tuned for some over the top particle effects in my future games! :-)

Python Education in Perth

Just recieved an invitation in my email to attend a bi-monthly game dev meetup at TAFE (A Technical College) in Perth, WA.

* Python * what is it and where to start:
You may have heard of Python * a very high level open source scripting language that has been used not only for introducing programming concepts to students but also for writing games scripts and controlling associated 3D rendering engines amongst many other applications and uses. Find out what you need to download to install Python and PyGame and the pit falls you will encounter to get it all up and running from a layman s perspective. See an example of what can be achieved after just a few days of development.
Presented by Steve Eggleston, Head of Programs, New Media Studies, Central TAFE

These chaps are using Python to teach game development! That's great! I wonder if they know of pyweek...

Monday, July 23, 2007

Generators hold references too!

For some reason, our TG app was leaking transactions, causing predictable crashes. Every page view, Postgres was holding onto transaction, which never committed.

Argh.

After much brute force debugging, I discovered the problem. A controller was calling a method in the model, and passing the return value through to the template, where incidentally, the value was no longer being used. "Easy fix", I thought, "just remove the method call."

But, I couldn't leave it at that, I had to find out what this method was doing differently which was causing transaction leakage... As it turns out, the method was returning a generator, via a generator expression. The generator itself was holding references to the transaction, preventing it from closing. The transaction would only close once the generator had been iterated through completely, finally calling the clean up code.

Woohoo. It's a good feeling when you kill a nasty bug like this. I'll be more careful with generator expressions from now on!

Sunday, July 22, 2007

Rectangle Operations

The Rect class in Pygame is very useful for normal screen based apps. It doesn't work so well in OpenGL code, which uses a left handed coordinate system (a positive Y axis). Also, pygame.Rect uses integers for internal coordinates, which means you cannot use it at sub-pixel accuracy.

So... I wrote a new Rect class to fix these problems.
easy_install rect

>>> from rect import Rect
>>> r = Rect((0,0,10,10))
>>> r.top
10.0
>>> r.bottom
0.0
Also included in the rect package is a quadtree spatial index, and a rectangle-bin packing function, useful for packing sprite strips, pre-rendered font characters or perhaps tile maps.

Update: Oops, a link would be helpful :-) http://cheeseshop.python.org/pypi/Rect/

Tuesday, July 10, 2007

A General Pygame Main-Loop

Will McGugan's post about mastering time in pygame started me thinking about my game loops, and how I might implement frame skipping, and other things.

The benefit of having a fixed 'step size' for your simulation might not be immediately apparent, however it has obvious benefits when trying to synchonrize network games, or work with physics libraries (eg ODE) which can go non-deterministic when working with a variable step size...

This is what my new general game loop looks like. If I ever need to implement frame-skipping, I believe I'll need to write some more code at line 27, to detect if every frame is being skipped... :-) I use this loop to generate Tick and Render events which get handled elsewhere.

1 import pygame
2 from pygame.locals import *
3
4 def main():
5 pygame.init()
6 pygame.display.set_mode((320,200))
7
8 #time is specified in milliseconds
9 #fixed simulation step duration
10 step_size = 20
11 #max duration to render a frame
12 max_frame_time = 100
13
14 now = pygame.time.get_ticks()
15 while(True):
16 #handle events
17 if QUIT in [e.type for e in pygame.event.get()]:
18 break
19
20 #get the current real time
21 T = pygame.time.get_ticks()
22
23 #if elapsed time since last frame is too long...
24 if T-now > max_frame_time:
25 #slow the game down by resetting clock
26 now = T - step_size
27 #alternatively, do nothing and frames will auto-skip, which
28 #may cause the engine to never render!
29
30 #this code will run only when enough time has passed, and will
31 #catch up to wall time if needed.
32 while(T-now >= step_size):
33 #save old game state, update new game state based on step_size
34 now += step_size
35 else:
36 pygame.time.wait(10)
37
38 #render game state. use 1.0/(step_size/(T-now)) for interpolation
39
40 if __name__ == "__main__":
41 main()

Update: Thanks to a suggestion from Marius in the comments, the loop is now environmentally friendly. :-)

Monday, July 09, 2007

Mediator Pattern in Python


1 class Mediator(object):
2 def __init__(self):
3 self.signals = {}
4
5 def signal(self, signal_name, *args, **kw):
6 for handler in self.signals.get(signal_name, []):
7 handler(*args, **kw)
8
0 def connect(self, signal_name, receiver):
10 handlers = self.signals.setdefault(signal_name, [])
11 handlers.append(receiver)
12
13 def disconnect(self, signal_name, receiver):
14 handlers[signal_name].remove(receiver)

This class helps promote loose coupling in my games. I imagine that with a few lines from Pygnet, I could probably 'loosely couple' objects over a network. :-)

Popular Posts