【问题标题】:Any way to speed up Python and Pygame?有什么方法可以加速 Python 和 Pygame?
【发布时间】:2011-06-18 12:15:23
【问题描述】:

我正在 Pygame 中编写一个简单的自上而下的 rpg,我发现它很慢......虽然我不希望 python 或 pygame 与使用 C/C++ 或 C/C++ 等编译语言制作的游戏的 FPS 相匹配像Java这样的事件字节编译的,但是pygame的当前FPS仍然像15。我尝试渲染16色位图而不是PNG或24位图,这稍微提高了速度,然后在绝望中,我将所有内容都切换为黑白单色位图,这使得 FPS 达到 35。但不是更多。现在根据我读过的大多数游戏开发书籍,如果用户对游戏图形完全满意,2d 游戏的 FPS 至少应该是 40,那么有什么方法可以提高 pygame 的速度吗?

【问题讨论】:

  • 你分析了吗?
  • 简介了吗?对不起,我不明白。请解释一下你想说什么。
  • 问题很可能出在您的代码中(与所有项目一样)。分析是找出位置的行为。在搜索框中输入“python profiling”or go here
  • 每个人都想教如何编写代码,但没有人想教如何正确地写代码:/ en.wikipedia.org/wiki/Profiling_%28computer_programming%29
  • 您必须分析代码。 “过早的优化是万恶之源”。您可以以 60fps 的速度轻松绘制一百张全彩 png 图像。所以你不需要优化图像。使用 png,除非您使用的是 3000,3000 像素的图像。

标签: python performance pygame frame-rate


【解决方案1】:

使用 Psyco,用于 python2:

import psyco
psyco.full()

另外,启用双缓冲。例如:

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

如果不需要,您也可以关闭 alpha:

screen.set_alpha(None)

不要每次都翻转整个屏幕,而是跟踪更改的区域并仅更新这些区域。例如,大致是这样的(主循环):

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)

大多数(全部?)绘图函数返回一个矩形。

您也可以只设置一些允许的事件,以便更快地处理事件:

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

另外,我不会手动创建缓冲区,也不会使用 HWACCEL 标志,因为我在某些设置中遇到了问题。

使用它,我已经为小型 2d 平台游戏实现了相当不错的 FPS 和流畅度。

【讨论】:

  • 谢谢,DOUBLEBUF 标志为我提供了实现 40 FPS 目标所需的最终提升。我将尝试渲染单独的矩形,但由于我的 rpg 的所有精灵首先被瓦片引擎blitted 到一个巨大的表面上,然后该表面在屏幕上被blit,它不会有很大的不同。谢谢!我终于得到了我想要的 40 FPS。 ^_^
  • "我的 rpg 的所有精灵首先被 tile 引擎 blitted 到一个巨大的表面上,然后这个表面被 blitted 到屏幕上" 是的,这是个问题。您应该只对需要进行 blitted 的内容进行 blit - 在 sprite 周围放置边界框,并且只对实际触摸屏幕的内容进行 blit。
  • @quantumpotato 在 2011 年已经很旧的笔记本电脑上超过 30 FPS,这是一款非常简单的平台游戏。在现代计算机上会快很多,但这完全取决于游戏、精灵的数量、背景是否滚动等。
  • 谢谢 - 我正在探索使用树莓派
  • Storm Claw,不是完整的程序,需要自己填空。 bpp 是“每像素位数”,通常为 8、16 或 24。有关更多信息,请查看 Pygame 文档,该文档非常棒。
【解决方案2】:

所有这些都是很好的建议并且效果很好,但您还应该记住两点:

1) Blitting 曲面到曲面上比直接绘制要快。因此,将固定图像预先绘制到表面上(在主游戏循环之外),然后将表面blitting 到主屏幕会更有效。例如:

# 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) 确保您不会通过绘制用户看不到的东西来浪费资源。例如:

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

这些是帮助我保持高 FPS 的一些一般概念。

【讨论】:

  • 我认为这是真的,blit 次要表面上的所有内容,然后在主循环的主表面中 blit 这个次要表面。我认为有用的另一件事是使用 sprite.Group() 将所有精灵添加到组中,然后一次绘制所有分组的精灵。
【解决方案3】:

使用图像时,使用图像的 convert() 函数转换它们很重要。 我读过 convert() 禁用了通常很慢的 alpha。 在我为图像使用 16 位颜色深度和转换功能之前,我也遇到了速度问题。现在我的 FPS 大约是 150,即使我在屏幕上显示一个大图像。

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

旋转和缩放也需要大量时间来计算。如果是不可变的,则可以将转换后的大图像保存在另一个图像中。

所以想法是计算一次并多次重复使用结果。

【讨论】:

  • 对于可能遇到与我相同的问题的其他人,使用 convert() 从精灵中删除 alpha 对我没有任何作用,但我忽略了背景图像。从我每次重绘的背景中删除 alpha 是巨大的性能提升。
【解决方案4】:

加载图像时,如果您绝对需要透明度或其他 alpha 值,请使用 Surface.convert_alpha() 方法。我一直将它用于我一直在编程的游戏中,它的性能有了巨大的提升。 例如:在您的构造函数中,使用以下命令加载图像:

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

据我所知,您对图像所做的任何转换都会保留此方法调用的性能。例如:

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

如果您使用的图像上运行了 convert_alpha(),就会变得多余。

【讨论】:

    【解决方案5】:

    首先,始终使用“convert()”,因为它会禁用 alpha,从而使 bliting 更快。 然后只更新屏幕需要更新的部分。

    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
    

    注意:

    移动精灵时,您必须在列表中包含其最后位置的矩形。

    【讨论】:

      【解决方案6】:

      您可以尝试使用 Psyco (http://psyco.sourceforge.net/introduction.html)。它通常会产生很大的不同。

      【讨论】:

      • 谢谢,但我试过 Psyco,虽然它确实加快了计算和程序执行速度,但我说的是图形渲染,不幸的是它对 pygame 的帧数没有任何作用每秒渲染。也许是因为 pygame 是 SDL 的包装器,所以也许所有的渲染都是在 C 中完成的?我在 C 语言中使用过 SDL,但它的速度并不为人所知。但它确实设法每秒显示 60-65 帧。
      猜你喜欢
      • 2015-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-22
      • 2016-02-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多