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

Re: [pygame] How fast is pygame meant to be?



Christian Perfect wrote:
> 	I'm a Blitz Basic (www.blitzbasic.com) user who's been playing
> aroudn with pygame, so the first thing I decided to do was to make a pygame
> version of the "firepaint" demo that comes with BB. It's a simple demo that
> shoots sparks from your mouse cursor that fall to the screen when you click
> the mouse.  I'm no good at optimising, so the code just follows the BB
> firepaint demo pretty closely. When I ran the demo, it ran *much* slower
> than the BB demo, at 8fps, whereas in BB it runs at my refresh rate (80fps+)
> Is pygame just not meant to be used for this kind of thing, and just
> blitting a few images and playing some sounds, or is there some secret
> different way of doing things I haven't found yet? :)

this big difference you are seeing is the difference between 
hardware accelerated graphics and not. i'm guessing blitzbasic only 
works with directx, therefore you probably only get hardware 
accelerated graphics.

in pygame you can also get hardware acceleration, but it's not 
always the case. i've made a couple changes to your code. it should 
now get hardware accelerated if it is supported on your system. i 
tested it on a NT4 machine with no directx. at 300mhz the program 
ran at 26fps with no frags, and 23fps with a couple explosions 
onscreen. with hardware acceleration i'm guessing you will also be 
at 80fps like bb.

here's the main set of changes i made (attached is the slightly new 
version)

first, you were assembling your 'set_mode()' flags slightly wrong. 
you had "HWSURFACE and DOUBLEBUF and FULLSCREEN". this is using 
python's "logical and" operation. what you need is the "bitwise or" 
operation. so this should become "HWSURFACE|DOUBLEBUF|FULLSCREEN".

second, i wrapped all the code into a function named "main". the 
main reason for this was so the game didn't need to access "global 
variables" when it is running. in python global vars are a little 
slower than normal local variables. in code that is called very 
frequently (like frag.update) you can start to notice this difference.

i changed the "pygame.draw.rect" code to "Surface.fill" which will 
do the same thing here for you. the Surface.fill has the benefit of 
being hardware accelerated when it can be.

that's pretty much it. i believe with the acceleration enabled this 
will run plenty quick for you. if not it could definitely be 
rearranged to run faster. if you want to explore that road let me know.

#Firepaint demo by Christian Perfect
#Based on the Blitz Basic firepaint demo by Mark Sibly
#This one's much slower :(

#Imports
import pygame
from pygame.locals import *
from random import *
from math import sin,cos


#frag class
class frag:
	#Create a frag, give it a random velocity
	def __init__(self,pos):
		self.pos=pos[:]
		an=randrange(1000)
		vel=randrange(3,4)
		self.move=[sin(an)*vel,cos(an)*vel]
		self.r=255
		self.g=255
		self.b=255
	#Update and draw frag
	def update(self, gravity, screen, frags):
		self.move[1]+=gravity
		self.pos[0]+=self.move[0]
		self.pos[1]+=self.move[1]
		if self.r <= 0 or self.pos[0]<0 or self.pos[0]>640 or self.pos[1]<0 or self.pos[1]>480:
			frags.remove(self)
			return
		if self.b>0:
			self.b-=5
		if self.g>0:
			self.g-=3
		if self.r>0:
			self.r-=1
		col=(self.r,self.g,self.b)
                screen.fill(col, (self.pos, (3,3)))


def main():
    #Init pygame
    pygame.init()
    pygame.font.init()
    myfont=pygame.font.Font(None,24)
    screen = pygame.display.set_mode([640,480], HWSURFACE|FULLSCREEN|DOUBLEBUF)
    hardware = ("software", "hardware")[screen.get_flags() & HWSURFACE == HWSURFACE]
    
    pygame.display.set_caption('Pygame Test')
    black = 0, 0, 0
    screen.fill(black)

    #Some variables
    frags=[]
    intensity=20	#Increase this for more frags!
    mousedown=0
    gravity=.1
    
    black=0,0,0
    white=255,255,255
    done=0
    clock=pygame.time.Clock()
    mousepos=[0,0]
    
    while not done:
            #Update frags
            for afrag in frags:
                    afrag.update(gravity, screen, frags)
                    
            #Check events
            for e in pygame.event.get():
                    if e.type == QUIT or (e.type == KEYUP and e.key == K_ESCAPE):
                            done=1
                            break
                    elif e.type == MOUSEBUTTONDOWN:
                            mousedown=1
                    elif e.type == MOUSEBUTTONUP:
                            mousedown=0
                    elif e.type == MOUSEMOTION:
                            mousepos=[e.pos[0],e.pos[1]]
            
            #Make new frags
            if mousedown:
                    mousedown = 0
                    for c in range(randrange(intensity,2*intensity)):
                            frags.append(frag(mousepos))
            
            #Calculate FPS
            clock.tick()
            fps = clock.get_fps()
            
            #Print fps and flame count on screen
            fpstext=myfont.render('%s FPS: %d'%(hardware, fps),0,white)
            counttext=myfont.render('No. Flames: '+str(len(frags)),0,white)
            screen.blit(fpstext,(0,0))
            screen.blit(counttext,(0,26))
            
            #Draw mouse cursor
            #pygame.draw.line(screen,white,(mousepos[0],mousepos[1]-5),(mousepos[0],mousepos[1]+5))
            #pygame.draw.line(screen,white,(mousepos[0]-5,mousepos[1]),(mousepos[0]+5,mousepos[1]))
            
            #Update display
            pygame.display.flip()
            screen.fill(black)
            
            
main()