虽然与实际的游戏开发框架相比,Pygame可能缺乏功能和优化,但它的低性能往往不是它的错。如果你的简单2D游戏出现了性能问题,问题在于你的编码,而不是Pygame。
在这篇关于提高Pygame性能的文章中,我们将解释到底如何才能提高你的游戏性能。最终的目标应该是稳定的帧率,在任何时候都没有明显的帧数下降。

如果你真的设法实施我在下面列出的所有提示和建议,你可以轻松地将你的游戏速度提高5倍(甚至更多)。即使是以下建议的一半,也可能足以让你获得你选择的稳定的帧率。但安全总比遗憾好(不是每个人都有一台好的电脑!)。
你可以查看我们网站上的许多Pygame项目,其中包括一个简单的汽车躲避游戏、平台游戏和一个RPG战斗机。
不要跳过任何一个项目,即使你已经能够将你的性能提高到你所要求的目标。并非所有这些都是为了提高速度,有些是为了改善加载时间和游戏中的音频同步性。所以请注意,直到最后。
在图片上使用convert()
每当你导入图片时,你应该总是对它们使用convert() 函数或convert_alpha() 函数。在处理这些图片时,这可以大大改善性能。
img = pygame.image.load("Background.png").convert()
在我们的一个Pygame项目中添加了这个函数,该项目广泛使用了50多张图片,使其性能提高了近5倍。
当图像要有一些透明度时,请使用convert_alpha() 。你在大多数时候都会需要这个。
升级到Pygame 2.0
经过十多年的开发(和延迟),Pygame 2.0最近已经发布。它带来了一大批支持新的和改进的功能,最重要的是,它改进和加快了Pygame引擎。在命令提示符下运行以下命令来升级Pygame。
pip install pygame --upgrade
杀死死亡的精灵(内存泄漏)
假设你有一个RPG游戏,你正在杀敌。每当你杀死一个敌人,你就阻止他们在屏幕上显示,使他们看起来好像已经死了。但这里有一个问题。你没有将他们从内存中删除,他们正在占用空间。
最终,你可能会达到一个点,即你在内存中有1000个敌人,其中只有5个可能是活的。由于你的游戏最多只能安全地处理100个,所以它开始出现可怕的滞后。这就是我们所说的内存泄漏,它是一个困扰所有游戏开发者(不仅仅是pygame)的真实问题。
简而言之,你需要适当地管理你如何摆脱无用/死亡的精灵。你需要把它们从游戏中完全删除,并为下一批精灵腾出它们所占用的内存。
这有点难以理解,甚至更难实现。但如果你真的想提高游戏的性能,你需要给它一些时间。
提高声音质量
这与提高Pygame的(速度)性能没有直接关系,但它确实可以改善你的声音质量,以及声音调用和实际声音之间的滞后。这是关于Pygame混音器,它在Pygame中处理音频。
pygame.mixer.pre_init(44100, 16, 2, 4096)
pygame.init()
在你的代码中加入上面这一行,就在pygame.init() ,将大大改善你的音频。它基本上是在Pygame之前初始化Pygame混音器,从而改善它。
第一个参数是频率(Hz),第二个是比特深度,第三个是通道数(单声道为1,立体声为2),最后一个是缓冲区大小。你可以调整这些值,只要你知道你在做什么。
停止无用的更新和渲染
没有必要更新你游戏中的一切,除非它被改变了。仅仅这一变化就可以使你的游戏速度提高100倍,这取决于你的情况有多严重。
我遇到过一个例子,有人在渲染一个巨大的3000 x 3000瓦的场地。在游戏循环的每一次迭代中,他都会对所有的瓷砖进行迭代,并对它们进行更新。通过改变事情,只渲染更新的瓷砖,他的游戏从2FPS上升到Pygame的最大极限2000。
简而言之,你需要正确评估你的代码,并想出一个办法,只更新那些被改变的东西。同样地,你也应该检查背景对象。如果某个东西目前没有被绘制到屏幕上,那么也没有必要更新它。只更新那些目前正在使用的对象。任何在屏幕外的东西也不需要被绘制。只有当它进入屏幕的视口时才会被绘制。
这是一个相当难实现的事情,而且在不同的游戏中差异很大(难度和方法)。但它也能产生最好的回报,所以绝对值得。
降低帧率
对于你的游戏来说,知道正确的帧率是很重要的。至少在pygame中,你的目标一般应该是30左右。任何低于这个数值的东西都太慢了,而任何高于这个数值的东西都会让你感到困难。Pygame并不像其他适当的游戏引擎那样得到很好的优化。
像国际象棋、鲁道、纸牌或任何涉及回合制运动的游戏,无论如何都不会从更高的帧率中受益。只要你遵循我们在这里提到的优化提示,你可以将流体运动游戏的帧率提高到60。
不要认为 "即使没有好处,保持较高的帧率有什么坏处"。好吧,首先它是你的设备上不必要的负载。其次,当帧率波动过大时,会产生微停顿,这实际上看起来很糟糕,使你的体验更差。
使用While(1)
这一点有点奇怪,而且影响很小,但写1而不是True,可以节省一个操作。这只是沧海一粟,但这样做也无妨,对吗? (这只对Python 2.x版本有明显的影响,而不是3.x及以上版本)

双重缓冲
一个简单的单行技巧可以给你的FPS带来一点提升,就是双缓冲和全屏标志。只需在你的程序中添加(或修改现有代码)以下几行代码。
from pygame.locals import *
flags = FULLSCREEN | DOUBLEBUF
screen = pygame.display.set_mode(resolution, flags, 16)
这将在一个特殊的全屏窗口中打开你的游戏,你的性能将得到轻微的改善。第三个参数是 "bit-per-pixel "或 "bpp"。
常见的每像素比特数是8、16和24。
只允许某些事件
pygame.event.set_allowed([QUIT, KEYDOWN, KEYUP])
这应该是相当明显的,为什么会提高性能。通过限制允许的Pygame事件的数量,你可以减少Pygame在游戏循环的每个迭代中必须进行的检查。
避免重复使用flip()
一旦我们对精灵在Pygame窗口中的位置做了改变,很多人就会调用pygame.display.flip() 或pygame.display.update() 函数。这里的问题是,你每做一次改变就会刷新整个窗口。这对性能有很大影响。
简而言之,你需要做两件事。在Game循环结束前不要调用flip() 或update() ,除非它实际上是某些任务所需要的。第二,尝试只更新特定的精灵,将精灵的矩形传入update() 函数。这样就只更新了那些特定的精灵,节省了大量的性能。
懒惰的加载模块
这是一个有用的小技巧,可以改善你的Pygame窗口的加载时间。与其在程序开始时就导入所有的模块,不如把它分散一下。
通常由于游戏的复杂性,你会使用很多库,这需要一点时间来实际加载。而且由于你在实际初始化 pygame 和开始绘制背景之前就做了这些,程序在进一步进行之前必须导入所有的模块。
简而言之,分散你的导入语句,只在它们真正需要的时候才导入。你可能想单独研究这个话题,并找出实现模块懒惰加载的最佳方法。
内建函数
我建议你使用 Python 的许多内置函数,而不是使用你自己的自定义函数。这些函数已经过严格的测试,比常规的或自定义的方法更安全、更快速。Python有40多个内置函数,你可以利用。
优化你的代码
这可能是你在这里听到的最普通的建议,但当涉及到提高性能时,它也是最有效的建议之一。不幸的是,这也是最困难的建议之一。你必须重新评估你所写的代码,并想出一个更好的方法来完成它。
无论你使用的是什么方法,几乎可以肯定有更好的方法来做。回到你所要做的事情的根源,并从那里开始工作。每次的答案都是独特的,在每个游戏中,对每个人都是如此。而且也没有捷径,所以想都别想。搜索 "Python剖析 "一词以了解更多关于这一技术的信息。
多线程
这是我想到的最后一种技术。说实话,如果你已经达到了觉得有必要实现多线程的地步(而其他什么都无济于事),你可能做错了什么。Pygame是一个简单的框架,实际上并不支持多线程等高级功能。
无论如何,我不建议在你可能创建的任何线程中使用Pygame相关代码。尽量只将计算代码移入线程,因为Pygame在线程上的行为可能相当奇怪,需要对子进程和进程进行一些复杂的设置(那是python中的一个库)。
请在评论区告诉我们,我们关于提高Pygame性能的提示是否有帮助,以及你的速度提高了多少