替换表面而不是对它进行 blitting

Posted

技术标签:

【中文标题】替换表面而不是对它进行 blitting【英文标题】:Replacing a surface instead of blitting to it 【发布时间】:2018-11-05 12:02:42 【问题描述】:

我在 pygame 中遇到了一些性能问题,所以我正在尝试优化渲染。

目前,我正在将背景图像传送到显示缓冲区:

self.display.blit(self.bg, (0, 0))

相反,我正在寻找一种方法来用背景表面的副本替换缓冲区,然后在上面绘制。这样,我不必每帧都对大图像进行 blit,从而节省了一些时间。

有什么办法吗?

【问题讨论】:

也许将整个框架构建到 self.bg 表面上,并且只有在构建完整个图像后才将其传送到显示器上?我不确定有没有办法将显示默认为图像 @vencaslac 这就是我现在正在做的事情,但这并没有有效地提高性能。此外,它不会清除图像,我仍在试图弄清楚。 【参考方案1】:

多久你在屏幕表面上显示一次并不重要,因为只有在你调用 pygame.display.updatepygame.display.flip 时,显示才会更新。

如果您确定将整个背景图像blitting 到屏幕表面游戏中的瓶颈,您可以尝试以下操作:

a) 使用clear() 函数从屏幕上“擦除”您的精灵,而不是每帧对整个背景进行blit。

b) 不要在没有参数的情况下调用pygame.display.flippygame.display.update,而是调用pygame.display.update 并使用draw() 函数返回的屏幕上已更改区域的列表(可能结合使用) clear())。

c) 使用 FULLSCREENDOUBLEBUFHWSURFACE 标志创建您的显示界面。

但正如我已经说过的:确保你知道你的瓶颈在哪里。一些常见的性能缺陷是:从磁盘多次加载图像、字体渲染、使用不同的像素格式(例如,不在从图像创建的表面上调用 convert/convert_alpha)以及通常缺乏缓存。

(另请注意,在创建图形要求高的游戏时,python/pygame 通常不是首选)

【讨论】:

【参考方案2】:

如果没有看到您的代码,就很难真正看出瓶颈在哪里。 Sloth 在他的观点上是正确的,这是一种优化的方式。根据我的经验,所有图像都应该在主游戏循环之外通过将它们绘制到它们自己的表面上进行预处理。将表面传送到表面比将图像传送到表面要快得多。

img_surface = pygame.Surface((img_rect.width, img_rect.height), pygame.SRCALPHA)
img_surface.fill((0, 0, 0, 0))
img_surface.blit(get_image("my_image.png"), img_rect)

这发生在游戏循环之外。在游戏循环中,您将图像表面粘贴到表面。如果您真的想评估您的代码,请使用 cProfile。这将帮助您确定瓶颈的确切位置。尽可能多地在主游戏循环之外进行预处理。

Python getting meaningful results from cProfile

这个链接确实帮助我理解了 cProfile。 Sloth 也是正确的,因为 pygame 是有限的,所以你需要尽可能地优化一切。这就是 cProfile 的用武之地。

...另外,请确保您只绘制用户可见的内容。这确实有助于提高性能。

【讨论】:

以上是关于替换表面而不是对它进行 blitting的主要内容,如果未能解决你的问题,请参考以下文章

VSCode 替换 _$ 而不是自动完成

前端打包,怎么只替换修改的文件,而不是整个项目替换?

Angular 4,热模块替换附加而不是替换

自定义键盘文本完全替换 UISearchBar 中的文本,而不是添加到其中 [iOS]

Pandas str 替换删除整个值而不是替换

通过对连续变量进行分组来替换分类变量的 NaN