Title: 'Vector Bob' Sprite/Particle ExampleAuthor: Diez B. Roggisch (deets at web.de) Description: A well known old demo effect. A set of 3d points is transformed and every point is blitted as a surface. Download: vector_bob.tgz pygame version required: Any with Surfarray Comments: This is a vector-driven particle toolkit, where each particle is a sprite, rather than a pixel. The example script allows you to see three basic data sets - choose between them with the '1', '2' and '3' keys (on the main keyboard, not the numeric keypad. This code, while not very thoroughly-commented, is concise and well-structured, and just about as fast as it can be. Consider using derivitives of this code for explosion or weapons effects, or for enemy movement routines in Galaxian-style games. |
""" Name : vector bob Desc : A well known old demo effect. A set of 3d points is transformed and every point is blitted as a surface. """ try: import sys, types, pygame, pygame.image, pygame.display, pygame.rect, pygame.key #, log4py import profile from Numeric import * #from collision import * except ImportError, e: print "import exception occured" print e sys.exit() MODE = (640, 480) BACKGROUND = None BALL = None class BobObject: """ A BobObject. The list _.coords are the coordinates of the points to be blitted """ def __init__(_, surface, scadjust): """ surface - the points are blitted as that scadjust - a tuple representing the screen (width/2, height/2) to center the transformed coordinates """ _.surface = surface _.coords = [] _.scadjust = scadjust - array(surface.get_rect().size) / 2 _.position = array((0,0,0)) _.reset() _.colObs = [] def translate(_, trans): _.position += trans def reset(_): _.orientation = array(identity(3), Float) def rotateZ(_, deg): rMat = array(identity(3), Float) cos = math.cos(deg) sin = math.sin(deg) rMat[0][0] = cos rMat[0][1] = -sin rMat[1][0] = sin rMat[1][1] = cos _.orientation = matrixmultiply(_.orientation, rMat) def rotateY(_, deg): rMat = array(identity(3), Float) cos = math.cos(deg) sin = math.sin(deg) rMat[0][0] = cos rMat[0][2] = -sin rMat[2][0] = sin rMat[2][2] = cos _.orientation = matrixmultiply(_.orientation, rMat) _.rot = deg def rotateX(_, deg): rMat = array(identity(3), Float) cos = math.cos(deg) sin = math.sin(deg) rMat[1][1] = cos rMat[1][2] = -sin rMat[2][1] = sin rMat[2][2] = cos _.orientation = matrixmultiply(_.orientation, rMat) def screenCoords(_): sc = [] _.colObs = [] for c in _.coords: p = matrixmultiply(c , _.orientation) + _.position sc.append((p[2], p[0] * 1000 / p[2] + _.scadjust[0], p[1] * 1000 / p[2] + _.scadjust[1])) sc.sort() sc.reverse() return map(lambda x: x[1:], sc) def getBobs(_): return map(lambda x, b=_.surface: (x, b), _.screenCoords()) class Cube(BobObject): def __init__(_, dim, surface, scad): def char(a): if a: return 1 return -1 BobObject.__init__(_, surface, scad) for i in xrange(8): _.coords.append((char(i & 1) * dim, char(i & 2) * dim, char(i & 4) * dim)) class Ring(BobObject): def __init__(_, dim, surface, scad, segments = 8): BobObject.__init__(_, surface, scad) for i in xrange(segments): x = dim * cos(math.pi * i / segments * 2) y = dim * sin(math.pi * i / segments * 2) _.coords.append((x, y, 0)) class Sphere(BobObject): def __init__(_, dim, surface, scad, segments = 8): BobObject.__init__(_, surface, scad) nums = [(1, 0)] for n in xrange(1, segments >> 1): deg = n / float(segments >> 1) * math.pi / 2 radius = dim * cos(deg) offset = dim * sin(deg) num = floor(segments * cos(deg)) if int(num) & 1: num += 1 for i in xrange(num): x = radius * cos(math.pi * i / num * 2) y = radius * sin(math.pi * i / num * 2) _.coords.append((x, y, offset)) _.coords.append((x, y, -offset)) for i in xrange(segments): x = dim * cos(math.pi * i / segments * 2) y = dim * sin(math.pi * i / segments * 2) _.coords.append((x, y, 0)) _.coords.append((0, 0, -dim)) _.coords.append((0, 0, dim)) class DisplayList: def __init__(_): _.saveStack = [] _.bobs = [] _.display = pygame.display.get_surface() def addBob(_, bob): # Create the rect in the display which has to be saved rect = bob[1].get_rect().move(bob[0]) bgSave = pygame.Surface(rect[2:]) bgSave.blit(_.display, (0,0), rect) _.saveStack.append((bob[0], bgSave, rect)) _.bobs.append(bob) def blitBobs(_): rectList = [] for bob in _.bobs: rectList.append(bob[1].get_rect().move(bob[0])) _.display.blit(bob[1], bob[0]) _.bobs = [] return rectList def restoreBackground(_): rectList = [] count = 0 y = 48 while len(_.saveStack): resBob = _.saveStack.pop() rectList.append(resBob[2]) _.display.blit(resBob[1], resBob[0]) count += 1 return rectList def main(): global DISPLAY global SCREENRECT global LEVEL global DIST_DEC DIST_DEC = 1 pygame.init() pygame.display.init() rect = (0, 0) + MODE DISPLAY = pygame.display.set_mode(MODE, 0) BACKGROUND = pygame.image.load("back.png").convert() BALL = pygame.image.load("ball.png").convert() BALL.set_colorkey(BALL.get_at((0,0))) DISPLAY.blit(BACKGROUND, (0, 0), BACKGROUND.get_rect()) dl = DisplayList() sc = array(BACKGROUND.get_rect()[2:])*0.5 vBob = Sphere(1000, BALL, sc) vBob.translate(array((0, 0, 10009))) pygame.display.update() oldts = pygame.time.get_ticks() -100 switchTs = oldts showBBox = 0 speed = 50.0 delay = 200 at = 0 r = 1.0 while 1==1: ts = pygame.time.get_ticks() elapsed = ts - oldts oldts = ts pygame.event.pump() keystate = pygame.key.get_pressed() if keystate[pygame.K_ESCAPE]: break if keystate[pygame.K_1]: vBob = Cube(1000 / 1.5, BALL, sc) vBob.translate(array((0, 0, 10009))) if keystate[pygame.K_2]: vBob = Sphere(1000, BALL, sc) vBob.translate(array((0, 0, 10009))) if keystate[pygame.K_3]: vBob = Ring(1000, BALL, sc) vBob.translate(array((0, 0, 10009))) invalidRects = dl.restoreBackground() vBob.reset() r = r + speed * elapsed / 1000 vBob.rotateX((r / 180.0) * math.pi) vBob.rotateY((r / 180.0) * math.pi) bobs = vBob.getBobs() for b in bobs: dl.addBob(b) invalidRects += dl.blitBobs() pygame.display.update(invalidRects) pygame.time.wait(50) if __name__ == "__main__": main() #profile.run('main()')
From: Korruptor |
Date: September 23, 2002 21:53 GMT |
Very nice! :-) |
From: krister |
Date: January 12, 2003 19:07 GMT |
The tar-ball has import log4py in it, that is not needed. It is commented out in the code on he webpage. |
Main - Repository - Submit - News |