提高显示性能

2024-04-26 05:05:15 发布

您现在位置:Python中文网/ 问答频道 /正文

所以我一直在我的游戏中添加一些东西,在添加了一个特别的东西之后,游戏变得相当滞后。我做了一些测试pygame.time.get\u滴答声()查看我的循环中的时间花在哪里,发现大约90%的时间花在两个位置。 1把我所有的精灵都吸引到屏幕上。 2绘制我的能力管理器,这只是绘制/布点一些图像。你知道吗

当移除convert()和convert_alpha()时,我感到困惑,在我的能力管理器中显著地提高了性能,然后移除绘制精灵时的转换似乎并没有影响性能。你知道吗

任何人都知道为什么转换会减慢速度,医生说这是最好的方法。还有,为什么它在一个领域有帮助而在另一个领域没有?你知道吗

编辑:一些数字来显示我的测试。 删除#2的转换,即能力管理器绘图,将绘制它们的平均时间从大约80毫秒减少到大约45毫秒。 移除或添加#1的转换,将精灵绘制到屏幕上,几乎不会影响做事的时间。影响范围为+5或-5。这个小小的改变可能不是移除转换的结果,所以我的问题应该主要集中在“为什么移除转换在能力管理器绘图中有这么大的帮助?”只有一点关于为什么它在一个领域而不是另一个领域会有如此大的帮助。你知道吗


Tags: 游戏绘图convert管理器get屏幕time时间
1条回答
网友
1楼 · 发布于 2024-04-26 05:05:15

警告:我不使用pygame但是我已经为高清视频编写了专业的定标器和转换器,所以我正在借鉴这种经验。你知道吗

我确实在这里查阅了文档:http://www.pygame.org/docs/ref/surface.html#pygame.Surface.convert

因此:

If no arguments are passed the new Surface will have the same pixel format as the display Surface. This is always the fastest format for blitting.

换句话说,如果格式匹配,那么它将运行得很快。但是,否则,它必须进行转换[这将运行得更慢]。你知道吗

It is a good idea to convert all Surfaces before they are blitted many times.

这可能是您想要做的(即保留一个缓存的后转换曲面副本,该副本与最终输出格式匹配)

对于你的精灵来说,它们应该相对较小,所以差别不大。对于更大的地区来说,这种转变可能[而且似乎]意义重大。你知道吗

与简单的blit不同,blit可以通过一系列快速的[C]memcpy操作来完成,转换必须逐像素完成。这可能涉及使用周围像素的卷积内核[对于一个好的定标器,我见过使用2d6抽头FIR滤波器]。你知道吗

由于精灵较小,转换器可能会选择更简单的转换算法,因为失真不太明显。对于较大的面积,转换器可能会选择更复杂的算法,因为失真会在较大的面积上累积。你知道吗

所以,再次强调,预加工将是一种方式。你知道吗

如果因为源区域在每一帧上都发生变化而不能这样做,则可能会引入一帧延迟,并在多个线程/内核中进行转换,将整个区域细分为跨线程的子区域。你知道吗


更新:

So, you note that at first, there would be a decrease in speed since pixel format must be changed.

游戏开始时的预计算应该不是问题,因为你的数字是80毫秒。用户甚至不会注意到启动游戏时有那么小的延迟。你知道吗

专业游戏用一个带有logo的“splash”页面来掩盖这一点,这个页面可能会做一个[琐碎的]动画(例如,只是改变颜色等)

But after the conversion at the start of the game, shouldn't the speed be better for the rest?

是的,它应该更快,根据你已经描述的:后续帧应该是45毫秒而不是80毫秒。现在给你一个22帧的帧速率就足够了。如果你仍然需要更快的速度(即达到30帧/秒),那么使用我已经提到的分区技术可能会有所帮助。另外,只有将第N帧更改为第N+1帧的内容稍加修改也会有所帮助。你知道吗

I'm still confused on why the speed throughout the game is slower if I converted.

下面是blit和convert的一些[粗略的]代码(即,只是为了说明不是真正的代码)。你知道吗

你现在所做的就像下面的blit_convert对于数据上的每个帧,我们称之为ability_manager_surface。你知道吗

请注意,它比简单的blit慢(例如下面的blit_fastblit_slow)。快速光点只是将每个源像素复制到目标像素。采样转换器必须取当前源像素及其最近邻像素的平均值,因此必须为每个目标像素提取五个源像素值。因此,速度较慢。真正的缩放算法可能更慢。你知道吗

如果您在游戏启动期间在ability_manager_surface上执行blit_convert,并将输出保存到一个“已转换”变量(例如precalc_manager_surface),则可以使用blit_fast在每个帧上使用precalc_manager_surface。也就是说,不需要重新计算“静态”数据。你知道吗

# dstv   destination pixel array
# dsthgt   destination height
# dstwid   destination width
#
# dstybase   destination Y position for upper left corner of inset
# dstxbase   destination X position for upper left corner of inset
#
# srcv   source pixel array
# srchgt   source height
# srcwid   source width

#                                        
# blit_fast   fast blit
# this uses a 1 dimensional array to be fast
def blit_fast(dstv,dsthgt,dstwid,dstybase,dstxbase,srcv,srchgt,srcwid):

    # NOTE: I may have messed up the equations here
    for yoff in range(dstybase,dstybase + srchgt):
        dstypos = (yoff * dstwid) + dstxbase
        srcypos = (yoff * srcwid);

        for xoff in range(0,srcwid):
            dstv[dstypos + xoff] = srcv[srcypos + xoff]

#                                        
# blit_slow   slower blit
# this uses a 2 dimensional array to be more clear
def blit_slow(dstv,dsthgt,dstwid,dstybase,dstxbase,srcv,srchgt,srcwid):

    for yoff in range(0,srchgt):
        for xoff in range(0,srcwid):
            dstv[dstybase + yoff][dstxbase + xoff] = srcv[yoff][xoff]

#                                        
# blit_convert   blit with conversion
def blit_convert(dstv,dsthgt,dstwid,dstybase,dstxbase,srcv,srchgt,srcwid):

    for yoff in range(0,srchgt):
        for xoff in range(0,srcwid):
            dstv[dstybase + yoff][dstxbase + xoff] = convert(srcv,yoff,xoff)

# convert   conversion function
# NOTE: this is more like a blur or soften filter
# the main point is this takes _more_ time than a simple blit
def convert(srcv,ypos,xpos):

    # we ignore the special case for the borders

    cur = srcv[ypos][xpos]

    top = srcv[ypos - 1][xpos]
    bot = srcv[ypos + 1][xpos]
    left = srcv[ypos][xpos - 1]
    right = srcv[ypos][xpos + 1]

    # do a [sample] convolution kernel
    # this equation probably isn't accurate   just to illustrate something that
    # is computationally expensive on a per pixel basis
    out = (cur * 0.6) + (top * 0.1) + (bot * 0.1) + (left * 0.1) + (right * 0.1)

    return out

注意:以上示例使用“toy”转换函数。要进行高分辨率/高质量的图像重缩放(例如1024x768>;1920x1080),您可能需要使用/选择“多相重采样”,并且计算量很大。例如,只需咧嘴一笑,请参见[令人难以置信]:https://cnx.org/contents/xOVdQmDl@10/Polyphase-Resampling-with-a-Ra


更新#2:

found the idea of only updating the stuff that moved helpful

这是实时动画和图形的标准建议。只需要重新计算你需要的。你只需要确定哪个是哪个。你知道吗

However, if I read correctly, you say that my game slows down after converting because I do it each frame.

根据你最初的描述,情况应该是这样。你知道吗

This isn't the case, as I convert at the very start, so it should be the fast blit you talk about, but it is faster if I never convert at all

没有你的代码,我很难推测。但是。。。你知道吗

创建曲面时(例如,保存.png之类的图像文件),默认格式是使用与屏幕非常匹配的格式格式。因此,它可以被blit而无需转换。你知道吗

所以,如果你预先转换一个屏幕外的表面,为什么它慢[到blit]如果转换后的格式匹配屏幕格式。如果速度慢一些,就会有不匹配的地方。而且,如果使用默认值创建曲面,为什么它需要转换?你知道吗

标准模式是尽可能直接在屏幕上进行操作。屏幕是“双缓冲”的,实际的渲染是通过主显示循环底部的pygame.display.flip完成的。你知道吗

所以,我不确定在你的程序中,曲面转换在哪里。你知道吗

下面是一些示例程序的链接[包括一些带有精灵的程序]:http://www.balloonbuilding.com/index.php?chapter=example_code

这只是“pygame示例程序”的“所有单词”网页搜索的一个链接。因此,如果你能将你所做的与他们进行比较,上面的链接(加上其他链接)可能会对你有所帮助。你知道吗

相关问题 更多 >