Python 提高显示性能
所以我一直在我的游戏中添加一些东西,在添加了一个特别的东西之后,游戏变得相当滞后。我使用pygame.time.get_ticks()进行了一些测试,以查看在我的循环中花费的时间,发现大约90%的时间花在两个位置。 1.将我所有的精灵绘制到屏幕上。 2.绘制我的能力管理器,它只是绘制/布点一些图像 当删除convert()和convert_alpha()时,我感到困惑,这大大提高了我的能力管理器的性能,而在绘制精灵时删除转换似乎并没有影响性能 任何人都知道为什么转换会减慢速度,医生说这是最好的方法。还有,为什么它能在一个领域有所帮助而在另一个领域却没有 编辑:一些数字显示我的测试。 删除能力管理器绘图#2的转换,将绘制转换的平均时间从大约80毫秒减少到大约45毫秒。 删除或添加#1的转换,将精灵绘制到屏幕上,几乎不会影响做事的时间。影响范围为+或-5。这个小小的改变可能不是删除转换的结果,所以我的问题应该主要集中在“为什么删除转换在能力管理器绘图中有这么大的帮助?”上,而仅仅是一点关于为什么它在一个领域而不是另一个领域有这么大的帮助。注意:我不使用Python 提高显示性能,python,performance,pygame,Python,Performance,Pygame,所以我一直在我的游戏中添加一些东西,在添加了一个特别的东西之后,游戏变得相当滞后。我使用pygame.time.get_ticks()进行了一些测试,以查看在我的循环中花费的时间,发现大约90%的时间花在两个位置。 1.将我所有的精灵绘制到屏幕上。 2.绘制我的能力管理器,它只是绘制/布点一些图像 当删除convert()和convert_alpha()时,我感到困惑,这大大提高了我的能力管理器的性能,而在绘制精灵时删除转换似乎并没有影响性能 任何人都知道为什么转换会减慢速度,医生说这是最好的方
pygame
,但我已经编写了定标器和转换器,就专业而言,高清视频,所以我借鉴了这一经验
我确实在这里查阅了文档:
由此:
如果未传递任何参数,则新曲面将具有与显示曲面相同的像素格式。这始终是最快的布告格式
换言之,如果格式匹配,它将运行得很快。但是,否则,它必须进行转换[这将运行得更慢]
最好在多次光点显示之前转换所有曲面
这可能就是您想要做的(即,保留与最终输出格式匹配的转换后曲面的缓存副本)
对于您的精灵,它们应该相对较小,所以差别不大。对于更大的地区,这种转变可能[而且似乎]意义重大
转换必须逐像素进行,而不是简单的blit(相当于)一系列快速[C]memcpy
操作。这可能涉及使用周围像素的卷积内核[对于一个好的定标器,我见过使用2D 6抽头FIR滤波器]
由于精灵较小,转换器可能会选择更简单的转换算法,因为失真不太明显。对于较大的面积,转换器可能会选择更复杂的算法,因为失真会在较大的面积上累积
因此,再次强调,预制将是一条出路
如果由于源区域在每一帧上发生变化而无法进行转换,则可能会引入一帧延迟,并在多个线程/内核中进行转换,从而将整个区域细分为跨线程的子区域
更新:
所以,您注意到,首先,由于必须更改像素格式,速度会降低 游戏开始时的预计算应该不是问题,因为您的数字是80毫秒。用户甚至不会注意到启动游戏时有这么小的延迟 专业游戏会用一个带有徽标的“飞溅”页面来掩盖这一点,该页面可能会制作一个[微不足道的]动画(例如,只是变形颜色,等等) 但是在比赛开始时转换后,其他人的速度不是更好吗 是的,根据您已经描述的,它应该更快:后续帧应该是45毫秒而不是80毫秒。现在给你一个22的帧速率,这可能足够了。如果你仍然需要加快速度(即达到30 fps),那么使用我已经提到的分区技术可能会有所帮助。此外,仅对已从第N帧更改为第N+1帧的内容进行点播也可能有所帮助 我仍然不明白,如果我转换,为什么整个游戏的速度会变慢 下面是blit和转换的一些[粗略]代码(即,只是为了说明——不是真正的代码) 您现在所做的是为数据上的每一帧执行下面的
blit\u convert
,我们称之为ability\u manager\u surface
请注意,它比简单的blit慢(例如下面的blit\u fast
或blit\u slow
)。快速光点只是将每个源像素复制到目标像素。采样转换器必须获取当前源像素及其最近邻像素的平均值,因此必须为每个目标像素获取五个源像素值。因此,速度较慢。真正的缩放算法可能更慢
如果您在游戏启动期间在ability\u manager\u surface
上执行blit\u convert
,并将输出保存到一个“已转换”变量(例如precalc\u manager\u surface
),则可以使用precalc\u surface
在每个帧上使用blit\u fast
。也就是说,不需要重新计算“静态”数据
注:上述示例使用“玩具”转换函数。要进行高分辨率/高质量的图像重缩放(例如,1024x768-->1920x1080),您可能需要使用/选择“多相重采样”,并且计算量非常大。例如,仅仅为了微笑,请参见[令人难以置信的想法]:
更新#2: 发现只更新移动的东西的想法很有帮助 这是实时动画和图形的标准建议。只需要重新计算你需要的。你只需要确定哪个是哪个 然而,如果我读对了,你会说我的游戏在转换后会变慢,因为我每一帧都会这样做 根据你最初的描述,情况应该是这样的 事实并非如此,因为我在一开始就转换,所以它应该是你所说的快速blit,但如果我
# 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