[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [pygame] Testing vector graphics



Leonardo Santagada wrote:
> 	Here is my test to make sure pygame could do a good job drawing
> vectors. It is not very well documented, nor it's finished. But I want
> to know from you all if I'm doing everything right and fast, because I'm
>  getting 99 fps just drawing one spaceship and I am using a PIII-850
> 384mb ram and a nvidia TNT2 card running the nvidia accelerated drivers
> for linux.

a couple things.. first, i like what you've done to the sprite 
classes. i think it's a good start. here's the biggest things i see.

first, you are clearing and flipping the entire screen for each 
frame. on my p2-300 at work the program runs at 35fps. not that the 
vector graphics are too slow, that is simply the maximum speed this 
computer can fill/flip an entire screen surface with software rendering.

with some minor changes i've got "teste" only updating the parts of 
the screen that are drawn to, and a cheap fix to only fill the parts 
of the screen that have a ship on them.

on my machine the framerate jumps up to over 800fps. now in the end 
this may not have such a benefit for you. if the real game has the 
entire screen filled with vector effects, you'll be at the same 
speed as the fullscreen fill/flip. i guess it just depends what the 
game is going to be if this will really benefit you or not.

also, the graphics card and driver will really not make much 
difference for you with this type of program. it is basically all 
software based, and the line rendering in pygame is done with 
software, so probably works best on regular software surfaces. it's 
really just a test of how quick the cpu can move pixels around in 
memory.

actually, i suppose with accelerated displays the fill and flip are 
done in hardware, so it could be a bit faster. i'm just unsure the 
speed of software line rendering on hardware surfaces...


hmm, actually, instead of filling the vector areas with black, you 
might be better off redrawing the lines with black? it might be 
worth trying.


#!/usr/bin/env python

#rotação(cartesiana)   Escala(cart.)
#  ([cos(x),-sen(x)],    ([],
#   [sen(x),cos(x))

import pygame,pygame.draw,pygame.time
from pygame.locals import *
from pygame.sprite import *
from Numeric import *

#constants
rotations=180 #how many rotations to generate
konstant=-5 #a costant for inverting and scaling all game objects

#create a cos and sin table
cost=[]
sint=[]
pirot=2*pi/rotations
for rotation in arange(0,rotations*pirot,pirot):
    cost.append(ceil(cos(rotation)*1000)/1000)
    sint.append(ceil(sin(rotation)*1000)/1000)

def rotate(data,rot):
    """rotate the matrix passed as data,
       and returns the new rotated matrix"""
    mrot=array([[cost[rot],-sint[rot]],
               [sint[rot],cost[rot]]])
    temp=matrixmultiply(mrot,data)
    return temp

def create_rotations(data):
    """Create the needed rotations for
       all vecobj"""
    rotlist=[]
    m=array([[konstant,0],
             [0,konstant]])
    tdata=matrixmultiply(m,data)
    for rot in range(rotations):
        rotlist.append(rotate(tdata,rot))
    return rotlist

class vecobj(Sprite):
    """Main descendant from sprite with
       support for vector graphics"""
    def __init__(self,pos,rot=0,color=(255,255,255)):
        Sprite.__init__(self, self.containers)
        self.color=color
        self.pos=pos
        self.data=self.images[rot%rotations]
        self.rot=rot%rotations
        
    def rotate(self,rot):
        self.data=self.images[rot%rotations]
        self.rot=rot%rotations

class naves(vecobj):
    pass

class RenderVectorPlain(Group):
    """Group used to draw vector objects"""

    def draw(self, surface):
        """draw(surface)
           draw all sprites onto a surface

           Draws all the sprites onto the given surface."""
        spritedict = self.spritedict
        surface_blit = draw_vecobj
        dirty = []
        for s in spritedict.keys():
            dirty.append(surface_blit(surface, s))
        return dirty

def draw_vecobj(surface,vecobj):
    """Draw objects in the screen"""
    tcolor=vecobj.color
    rect = pygame.draw.lines(surface, tcolor, 0, transpose(vecobj.data+vecobj.pos))
    return rect.inflate(4, 4)

def main():
    pygame.init()
    screen = pygame.display.set_mode((640,480),1|DOUBLEBUF,16)

    #data for some objects
    anave=array([[0,1,3,3,0,-3,-3,-1,0],[5,0,2,-2,-1,-2,2,0,5]])
    acasa=array([[5,5,-5,-5,5,4,4,2,2,5,5,0,-5],[-5,5,5,-5,-5,-5,-1,-1,-5,-5,5,8,5]])

    #Group and Sprite stuff
    vectors=RenderVectorPlain()
    naves.containers= vectors
    
    naves.images=create_rotations(anave)

    nave1=naves(array([[160],[100]]))
    
    frames=0
    ticks=pygame.time.get_ticks()
    while 1:
	event = pygame.event.poll()
	if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
            break
        keystate = pygame.key.get_pressed()
        directionx = keystate[K_RIGHT] - keystate[K_LEFT]
        directiony = keystate[K_DOWN] - keystate[K_UP]
        nave1.pos[1]+=directiony
        nave1.rotate(nave1.rot+directionx)

        dirty = vectors.draw(screen)
        pygame.display.update(dirty)
        for d in dirty:
            screen.fill(0, d)
        frames = frames+1

    print "fps:  %d" % ((frames*1000)/(pygame.time.get_ticks()-ticks))

#this is the python code to quickstart the program if not imported
if __name__ == '__main__': main()