Any way to speed up Python and Pygame?

前端 未结 6 1469
故里飘歌
故里飘歌 2020-12-28 08:37

I am writing a simple top down rpg in Pygame, and I have found that it is quite slow.... Although I am not expecting python or pygame to match the FPS of games made with com

相关标签:
6条回答
  • 2020-12-28 08:57

    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.

    0 讨论(0)
  • 2020-12-28 09:07

    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.

    0 讨论(0)
  • 2020-12-28 09:09

    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.

    0 讨论(0)
  • 2020-12-28 09:12

    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.

    0 讨论(0)
  • 2020-12-28 09:19

    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.

    0 讨论(0)
  • 2020-12-28 09:19

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

    0 讨论(0)
提交回复
热议问题