Any way to speed up Python and Pygame?

怎甘沉沦 提交于 2019-11-30 05:16:14

Use Psyco, for python2:

import psyco
psyco.full()

Also, enable doublebuffering. For example:

from pygame.locals import *
flags = FULLSCREEN | DOUBLEBUF
screen = pygame.display.set_mode(resolution, flags, bpp)

You could also turn off alpha if you don't need it:

screen.set_alpha(None)

Instead of flipping the entire screen every time, keep track of the changed areas and only update those. For example, something roughly like this (main loop):

events = pygame.events.get()
for event in events:
    # deal with events
pygame.event.pump()
my_sprites.do_stuff_every_loop()
rects = my_sprites.draw()
activerects = rects + oldrects
activerects = filter(bool, activerects)
pygame.display.update(activerects)
oldrects = rects[:]
for rect in rects:
    screen.blit(bgimg, rect, rect)

Most (all?) drawing functions return a rect.

You can also set only some allowed events, for more speedy event handling:

pygame.event.set_allowed([QUIT, KEYDOWN, KEYUP])

Also, I would not bother with creating a buffer manually and would not use the HWACCEL flag, as I've experienced problems with it on some setups.

Using this, I've achieved reasonably good FPS and smoothness for a small 2d-platformer.

When loading images, if you absolutely require transparency or other alpha values, use the Surface.convert_alpha() method. I have been using it for a game I've been programming, and it has been a huge increase in performance. E.G: In your constructor, load your images using:

self.srcimage = pygame.image.load(imagepath).convert_alpha() 

As far as I can tell, any transformations you do to the image retains the performance this method calls. E.G:

self.rotatedimage = pygame.transform.rotate(self.srcimage, angle).convert_alpha()

becomes redundant if you are using an image that has had convert_alpha() ran on it.

When using images it is important to convert them with the convert()-function of the image. I have read that convert() disables alpha which is normally quite slow. I also had speed problems until I used a colour depth of 16 bit and the convert function for my images. Now my FPS are around 150 even if I blit a big image to the screen.

image = image.convert()#video system has to be initialed

Also rotations and scaling takes a lot of time to calculate. A big, transformed image can be saved in another image if it is immutable.

So the idea is to calculate once and reuse the outcome multiple times.

All of these are great suggestions and work well, but you should also keep in mind two things:

1) Blitting surfaces onto surfaces is faster than drawing directly. So pre-drawing fixed images onto surfaces (outside the main game loop), then blitting the surface to the main screen will be more efficient. For exmample:

# pre-draw image outside of main game loop
image_rect = get_image("filename").get_rect()
image_surface = pygame.Surface((image_rect.width, image_rect.height))
image_surface.blit(get_image("filename"), image_rect)
......
# inside main game loop - blit surface to surface (the main screen)
screen.blit(image_surface, image_rect)

2) Make sure you aren't wasting resources by drawing stuff the user can't see. for example:

if point.x >= 0 and point.x <= SCREEN_WIDTH and point.y >= 0 and point.y <= SCREEN_HEIGHT:
    # then draw your item

These are some general concepts that help me keep FPS high.

First, always use 'convert()' because it disables alpha which makes bliting faster. Then only update the parts of the screen that need to be updated.

global rects

rects = []

rects.append(pygame.draw.line(screen, (0, 0, 0), (20, 20), (100, 400), 1)) 

pygame.display.update(rects) # pygame will only update those rects

Note:

When moving a sprite you have to include in the list the rect from their last position.

You could try using Psyco (http://psyco.sourceforge.net/introduction.html). It often makes quite a bit of difference.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!