Pygame在屏幕上移动线条时会出现画面撕裂问题。

5
我正在尝试移动这张图片: enter image description here 在我的PyGame屏幕上,从右到左再返回。但是随着图片的移动,每秒钟都会有一次屏幕撕裂,就像这样: enter image description here 我使用的代码循环类似于这样:
screen.blit(img, (x,y))
pygame.update((x,y),(w,h))
pygame.draw.rect(screen,(0,0,0),((x,y),(w,h)))

到目前为止,我已经尝试了以下方法来解决问题:
在创建屏幕时使用HWSURFACE、FULLSCREEN和DOUBLEBUF标志,但没有效果,我还将我的.update(rect)调整为.flip()(因为在使用DOUBLEBUF时建议这样做?)
将内存分配到GPU和CPU之间(我正在运行树莓派2),我尝试给两者都更多的内存,但没有改变。
将clock.tick设置为60 FPS以限制更新速率(高于和低于60 FPS),这确实平滑了一些撕裂,但并非全部。
调整每个增量向左或向右的大小,使增量较小可以减少撕裂,但速度也会降低。(不能让它太慢)
将新的黑色表面blit而不是在移动图像时绘制黑色矩形以确保其后面没有痕迹,因为我在某个地方读到blit使用HWSURFACE比绘图更好支持,虽然我无法证实这一点?- 这没有效果。
如果有人有其他可以改善情况的解决方案,我会非常感激。
我宁愿不要从PyGame更改到其他任何东西(如pyglet),因为我已经使用PyGame进行了相当多的实现,但我愿意听取建议。
干杯
编辑
如所请求,相关代码:
if scanner == True:
    clocker.tick(clockspeed)
    if x < 11:
        slower = 3
        if firstTime == True:
            img.set_alpha(int(x * 25))
            newSurf.set_alpha(int(x * 25))
            screen.blit(newSurf,(xText,35))
            pygame.display.update((xText,35),((xText + newSurf.get_width()),(50 + newSurf.get_height())))
            img.set_alpha(255)

    elif x > (divider - 15):
        slower = 3
    else:
        slower = 0
        firstTime = False

    screen.blit(img, ((xStart - (x * increment) + slower),100))
    pygame.display.update(((xStart - (x * increment) + slower),100),(95,450))
    pygame.draw.rect(screen, (0,0,0), (((xStart - (x * increment) + slower),100),(95,450)))

变量 slower 旨在在进度条扫过速度的最左侧和最右侧时,给人一种惯性感,它会稍微减慢速度。

变量 firstTime 用于在进度条首次出现时淡入显示。

下面还有一个非常相似的循环,但是将图像扫回到另一侧。


我知道你提供给我们的代码是伪代码,但是为什么你先更新屏幕再绘制矩形呢?顺便说一下,应该是 pygame.draw.rect(screen,(0,0,0),((x,y),(w,h))),因为第三个参数是一个 pygame.Rect 对象 :) - elegent
啊,是的,在编写伪代码时漏掉了几个括号,我现在会进行编辑,你发现得真好! :) 我在更新后绘制矩形,因为这是在循环中运行的,而且矩形是用来覆盖图像之前位置的,我可以将矩形绘制移动到代码的第一行,它会表现相同。 - Aphire
没问题 :) 如果可以的话,你能发一下你的主游戏循环代码吗? - elegent
很遗憾,这并不是一个游戏,我正在使用pygame为我的Python程序制作一个漂亮的GUI界面。请给我一分钟,我将发布相关代码部分。 - Aphire
2个回答

1

设置

vsync = true

pygame.display.set_mode()


0

这种撕裂只是屏幕呈现的方式所产生的。线条的下一个位置在渲染时,上一个位置正在被绘制覆盖。如果屏幕的刷新率和更新率是同步的,那么这个问题就消失了。但由于准确地做到这一点是几乎不可能的,我建议像 PICO-8 一样管理它,等待屏幕刷新完成后再更改屏幕缓冲区以防止撕裂。我不确定是否有一种方法可以等待屏幕刷新完成,但如果有的话,序列应该是:更新后备缓冲区 -> 等待屏幕停止绘制 -> 翻转缓冲区 -> 屏幕再次被绘制

刷新是指屏幕从左到右、从上到下、逐像素绘制的过程。这是因为与屏幕的三倍总线连接只允许一个像素亮度从屏幕内存中出来,因此每个像素都按顺序绘制。撕裂来自于在刷新中途内存发生变化,因此线条在屏幕中部向下移动位置。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接