[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] Paralax snow flakes: Some tipps for enhancing the performance



Hmm, i just sent this message, but it neither appeard in the ASPN Mailing List Archive nor i found it in my mail box ... sorry if you get this twice, i'm not very used to mailing lists....
------------------------------------------------------------------------ -------------------------------------

Hi! Firstly, thank you!

I tryed to add the FULLSCREEN command, but unfortunately it was the same in high resolution... around 15 fps..

This is how it looked like:
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT), HWSURFACE|DOUBLEBUF |FULLSCREEN)

Hmm... then i wanted to test this "Dirty Rectangles"-Methode. I have heard of this in my BlitzBasic-Time, and i think i got the idea...

So here's how i changed my code:

#Schnefall mit Dirty Rectangles 0.1

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

#Konstanten
MAX_FLOCKEN = 100
MAX_FLOCKEN_SPEED = 5
MAX_FLOCKEN_SIZE = 3
SCREEN_HEIGHT = 400
SCREEN_WIDTH = 400
SIN_FREQUENZ = 2

#Klassendefinitionen
class Flocke:
#Initialisierung jeder neuen Flocke
def __init__(self):
self.speed = random.randint(1,MAX_FLOCKEN_SPEED)
helligkeit = random.randint(20*self.speed,50*self.speed)
self.color = (helligkeit, helligkeit, helligkeit)
self.size = random.randint(1, MAX_FLOCKEN_SIZE)
self.ypos = random.randint(1,SCREEN_HEIGHT)
self.xpos = random.randint(1,SCREEN_WIDTH)
self.angle = random.randint(0,360)

#Methode zum Darstellen der Flocken
def draw(self):
return screen.fill(self.color, (self.xpos, self.ypos, self.size, self.size))

#Eigenschaften einer Flocke updaten
def update(self):
self.ypos = self.ypos + self.speed
self.xpos = self.xpos + (math.sin(self.angle)*5)
self.angle = self.angle + 0.1

if self.angle >= 360:
self.angle=0

if self.ypos > SCREEN_HEIGHT:
self.ypos = 0



#Standardinitialisierungen
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT), HWSURFACE|DOUBLEBUF)
pygame.display.set_caption('Paralaxer Schneefall')
pygame.mouse.set_visible(0)

#Hintergrund erschaffen
background = pygame.Surface(screen.get_size())
background = background.convert()
background.fill((0,0,0))

#Erschaffen der Sterne
flockerl = []
for x in range(0,MAX_FLOCKEN):
flockerl.append(Flocke())

#Dirty Rectangles
dirty = []

#Main Loop
def main():
frames=0
ticks = pygame.time.get_ticks()

while 1:
for i in dirty:
screen.blit(background, dirty, dirty)
old_dirty = dirty
dirty = []

for jede_flocke in flockerl:
jede_flocke.update()
dirty.append(jede_flocke.draw())

pygame.display.update(old_dirty + dirty)
pygame.display.flip()

frames=frames+1
keyinput = pygame.key.get_pressed ()
if keyinput [ K_ESCAPE] or pygame.event.peek(QUIT):
break
print "fps: %d" % ((frames*1000)/(pygame.time.get_ticks()-ticks))


if __name__=='__main__':
main()

By mischance the Interpreter splits out this:

File "schneeflocken_dirty_rects.py", line 69, in main
for i in dirty:
UnboundLocalError: local variable 'dirty' referenced before assignment

Hmm, i don't really understand this error message. It means something like "want's to deal with a variable which hasn't been declared yet" ??? Hmm, i think will toy around with this problem a little bit!

greets, Ludwig


Am Sonntag, 02.05.04, um 05:51 Uhr (Europe/Berlin) schrieb Pete Shinners:

Ludwig, the problem you are seeing is not that the snow is any slower, but the amount of time needed to draw the background and update the screen takes longer.

The code you have written seems good.

In Pygame and SDL everything defaults to software by defualt. You can force your display to be hardware accelerated, but you have to ask for it, and it only works in FULLSCREEN display modes.

To get the hardware acceleration, add the FULLSCREEN flag to your HWSURFACE|DOUBLEBUF.

Most pygame projects use the software display modes and keep track of the modified areas of the screen (the "dirty rectangles"). By tracking these you know exactly what to update and your project will basically run the same speed. Here is what you'd want to change from your source to speed it up with software mode.

First, change the Flocke.draw to return the value from fill.

def draw(self):
return screen.fill(self.color, (self.xpos, self.ypos, self.size, self.size))

Before your loop create an empty list named "dirty". Then change the loop to look like this.


while 1:
for r in self.dirty:
screen.blit(background, dirty, dirty)
old_dirty = dirty
dirty = []

for jede_flock in flockerl:
jede_flocke.update()
dirty.append(jede_flocke.draw())

pygame.display.update(old_dirty + dirty)


Hopefully that is understandable. It doesn't take a lot of code at this point to track the changed areas and only work with them.