简体   繁体   English

有什么办法可以加快 Python 和 Pygame 的速度吗?

[英]Any way to speed up Python and Pygame?

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 compiled languages like C/C++ or event Byte Compiled ones like Java, But still the current FPS of pygame is like 15. I tried rendering 16-color Bitmaps instead of PNGs or 24 Bitmaps, which slightly boosted the speed, then in desperation, I switched everything to black and white monochrome bitmaps and that made the FPS go to 35. But not more.我正在 Pygame 中编写一个简单的自上而下的 rpg,我发现它很慢....虽然我不希望 python 或 pygame 匹配使用 C/C++ 或事件字节编译等编译语言制作的游戏的 FPS像 Java 这样的,但 pygame 的当前 FPS 仍然是 15。我尝试渲染 16 色位图而不是 PNG 或 24 位图,这稍微提高了速度,然后在绝望中,我将所有内容切换为黑白单色位图,然后使 FPS go 达到 35。但不是更多。 Now according to most Game Development books I have read, for a user to be completely satisfied with game graphics, the FPS of a 2d game should at least be 40, so is there ANY way of boosting the speed of pygame?现在根据我读过的大多数游戏开发书籍,为了让用户对游戏图形完全满意,2d 游戏的 FPS 至少应该是 40,那么有什么方法可以提高 pygame 的速度吗?

Use Psyco, for python2: 使用Psyco,用于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: 如果您不需要,也可以关闭alpha:

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. 大多数(全部?)绘图函数返回一个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. 此外,我不打算手动创建缓冲区,也不会使用HWACCEL标志,因为我在某些设置上遇到了问题。

Using this, I've achieved reasonably good FPS and smoothness for a small 2d-platformer. 使用这个,我已经为小型2d平台器获得了相当好的FPS和平滑度。

When using images it is important to convert them with the convert()-function of the image. 使用图像时,使用图像的convert()函数进行转换非常重要。 I have read that convert() disables alpha which is normally quite slow. 我已经读过convert()禁用alpha,这通常很慢。 I also had speed problems until I used a colour depth of 16 bit and the convert function for my images. 我也有速度问题,直到我使用16位的颜色深度和我的图像的转换功能。 Now my FPS are around 150 even if I blit a big image to the screen. 现在我的FPS大约是150,即使我在屏幕上显示一个大图像。

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. 因此,想法是计算一次并多次重复使用结果。

When loading images, if you absolutely require transparency or other alpha values, use the Surface.convert_alpha() method. 加载图像时,如果绝对需要透明度或其他alpha值,请使用Surface.convert_alpha()方法。 I have been using it for a game I've been programming, and it has been a huge increase in performance. 我一直在使用它进行我编程的游戏,并且性能大幅提升。 EG: In your constructor, load your images using: EG:在构造函数中,使用以下命令加载图像:

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. 据我所知,您对图像所做的任何转换都会保留此方法调用的性能。 EG: 例如:

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. 如果您正在使用已运行convert_alpha()的图像,则会变得多余。

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. 1)在表面上模糊表面比直接绘制更快。 So pre-drawing fixed images onto surfaces (outside the main game loop), then blitting the surface to the main screen will be more efficient. 因此,将固定图像预先绘制到曲面上(主游戏循环外部),然后将曲面blitting到主屏幕将更有效。 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. 2)确保你没有通过绘制用户看不到的东西来浪费资源。 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. 这些是帮助我保持高FPS的一些一般概念。

First, always use 'convert()' because it disables alpha which makes bliting faster. 首先,总是使用'​​convert()',因为它会禁用alpha,这会使blit更快。 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). 您可以尝试使用Psyco(http://psyco.sourceforge.net/introduction.html)。 It often makes quite a bit of difference. 它通常会产生很大的不同。

There are a few things to consider for a well-performing Pygame application:对于性能良好的 Pygame 应用程序,需要考虑以下几点:

  • Ensure that the image Surface has the same format as the display Surface .确保图像Surface与显示Surface具有相同的格式。 Use convert() (or convert_alpha() ) to create a Surface that has the same pixel format.使用convert() (或convert_alpha() )创建具有相同像素格式的Surface This improves performance when the image is blit on the display, because the formats are compatible and blit does not need to perform an implicit transformation.这提高了图像在显示器blit时的性能,因为格式兼容并且blit不需要执行隐式转换。 eg:例如:

     surf = pygame.image.load('my_image.png').convert_alpha()
  • Do not load the images in the application loop.不要在应用程序循环中加载图像。 pygame.image.load is a very time-consuming operation because the image file must be loaded from the device and the image format must be decoded. pygame.image.load是一个非常耗时的操作,因为必须从设备加载图像文件并且必须解码图像格式。 Load the images once before the application loop, but use the images in the application loop.在应用程序循环之前加载一次图像,但在应用程序循环中使用图像。

  • If you have a static game map that consists of tiles, you can buy performance by paying with memory usage.如果你有一个 static 游戏 map 由瓷砖组成,你可以通过支付 memory 使用费来购买性能。 Create a large Surface with the complete map. blit the area which is currently visible on the screen:用完整的blit创建一个大的Surface当前在屏幕上可见的区域:

     game_map = pygame.Surface((tile_size * columns, tile_size * rows)) for x in range(columns): for y in range(rows): tile_image = # image for this row and column game_map.blit(tile_image, (x * tile_size, y * tile_size))
     while game: # [...] map_sub_rect = screen.get_rect(topleft = (camera_x, camera_y)) screen.blit(game_map, (0, 0), map_sub_rect) # [...]
  • If the text is static, the text does not need to be rendered in each frame.如果文本是static,则不需要每一帧都渲染文本。 Create the text surface once at the beginning of the program or in the constructor of a class, and blit the text surface in each frame.在程序的开头或在一个class的构造函数中创建一次文本表面,并在每一帧中blit文本表面。

  • If the text is dynamic, it cannot even be pre-rendered.如果文本是动态的,它甚至不能被预渲染。 However, the most time-consuming is to create the pygame.font.Font / pygame.font.SysFont object. At the very least, you should avoid creating the font in every frame.但是,最耗时的是创建pygame.font.Font / pygame.font.SysFont object。至少,您应该避免在每一帧都创建字体。
    In a typical application you don't need all permutations of fonts and font sizes.在典型的应用程序中,您不需要 fonts 和字体大小的所有排列。 You just need a couple of different font objects.您只需要几个不同的font对象。 Create a number of fonts at the beginning of the application and use them when rendering the text.在应用程序的开头创建一个数字 fonts 并在渲染文本时使用它们。 For Instance.例如。 eg:例如:

     fontComic40 = pygame.font.SysFont("Comic Sans MS", 40) fontComic180 = pygame.font.SysFont("Comic Sans MS", 180)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM