【问题标题】:Pygame Screen tearing when moving line across screenPygame在屏幕上移动线时屏幕撕裂
【发布时间】:2015-09-05 07:53:24
【问题描述】:

我正在尝试移动这张图片:

在我的 PyGame 屏幕上,从右到左再回来,但是随着图像的移动,每隔一秒左右我就会有一个闪烁的屏幕撕裂,就像这样:

我使用的代码是一个类似这样的循环:

screen.blit(img, (x,y))
pygame.update((x,y),(w,h))
pygame.draw.rect(screen,(0,0,0),((x,y),(w,h)))

到目前为止,我已尝试以下方法来解决此问题:

在创建屏幕时使用HWSURFACEFULLSCREENDOUBLEBUF标志,这没有效果,我还将我的.update(rect)调整为.flip()(因为在使用DOUBLEBUF时建议这样做?)

在 GPU 和 CPU 之间拆分内存(我在树莓派 2 上运行此程序)我尝试给两者都提供更多内存,没有任何变化。

设置一个clock.tick 将更新速率限制为60 FPS(高于和低于)这确实消除了一些撕裂,但不是全部

向左或向右调整每个增量的大小,使增量更小会减少撕裂,但也会降低速度。 (不能让它慢)

当我在某处读到blit 比绘图更好地支持blit 时,在之前的位置上绘制一个新的黑色表面而不是在之前的位置上绘制一个黑色矩形(当移动图像以确保它后面没有痕迹时),虽然我无法确认这一点? - 这没有效果

如果有人有任何其他可以改善这种情况的解决方案,我将不胜感激。

我宁愿从 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 对象:)
  • 啊,是的,在抛出伪时错过了我们的几个括号,我现在将编辑,好地方! :) 我在更新后绘制矩形,因为它在循环中运行,并且矩形是在图像的先前位置上绘制,我可以将矩形绘制移动到代码的第一行,它的行为相同
  • 完全没有问题 :) 如果可以的话,你能发布你的主游戏循环代码吗?
  • 不幸的是,这实际上不是一个游戏,我正在使用 pygame,所以我可以为我的 Python 程序制作一个漂亮的 GUI。给我一分钟,我将发布相关的代码部分

标签: python pygame raspberry-pi vsync


【解决方案1】:

设置

vsync = true

pygame.display.set_mode()

【讨论】:

    【解决方案2】:

    这种撕裂只是屏幕渲染方式的产物。线的下一个位置正在渲染,而前一个位置正在被绘制。如果屏幕的刷新率和更新率是同步的,那么这个问题就会消失。但由于这几乎不可能做到准确,我建议让您的程序采用 PICO-8 管理此问题的路线,等待屏幕刷新完成,然后再更改屏幕缓冲区以防止撕裂。我不确定是否有等待屏幕刷新完成的方法,但如果有,那么序列应该是:update back buffer -&gt; wait for screen to stop being drawn -&gt; flip buffers -&gt; screen is drawn again

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-26
      • 2012-10-27
      • 1970-01-01
      • 2012-09-09
      相关资源
      最近更新 更多