【问题标题】:"pygame.display.update()" does not clear blit image“pygame.display.update()”不清除 blit 图像
【发布时间】:2016-06-10 20:51:50
【问题描述】:

我有一个更新图像的主循环:

循环:

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
    self.spaceship.buttons()
    self.spaceship.update(self.screen)
    pygame.display.update()

self.spaceship.buttons() 在哪里:

def buttons(self):
    key = pygame.key.get_pressed()
    dist = 1
    if key[pygame.K_LEFT]:
        self.x -= dist
    elif key[pygame.K_RIGHT]:
        self.x += dist

并定义了self.spaceship.update(self.screen)

def update(self, surface):
    surface.blit(self.image, (self.x, self.y))

在主循环更新按键并将图像“blit”到屏幕上之后,它应该更新显示(pygame.display.update()),但屏幕不会被清除。这是移动前后的显示效果:

This is what the image looks like before the blit at a different position

This is what the image looks like after the blit is at a different position (after moving)

为什么pygame.display.update()不清除图片的前几帧?

【问题讨论】:

    标签: python pygame


    【解决方案1】:

    这很简单,pygame 不会为您执行此操作。
    pygame.display.update() 更新整个场景以向用户显示新内容您已“闪烁”。它不会抹去过去。

    它也可以用来只更新你知道你已经做了一些更新的某些区域(以加快速度)。

    或者,您可以执行flip() 来更新整个图形缓冲区,使其仅包含自上次翻转以来您已闪烁的新内容(请注意,您将丢失此循环中未包含的所有内容):

    while True:
        ...
        pygame.display.flip()
    

    或者,您只需在调用 update 之前“绘制”一个黑框。
    然而,这更加繁重。

    while True:
        ...
        self.screen.fill((0,0,0))
        pygame.display.update()
    

    我的建议是,您要么使用draw_rect 并在之前的宇宙飞船所在区域绘制一个黑色矩形,要么简单地使用flip() 切换到GPU 中的新缓冲区页面。在大多数实现中,执行flip() 非常快。

    我来自Pyglet背景,所以flip()update()draw_rect()的速度性能在Pygame中可能会有所不同,但基本原理应该是一样的,我的回答应该是有效的,如果不是请指出这个出来了。

    【讨论】:

      【解决方案2】:

      Pygame 只会绘制你告诉它的内容。如果你只告诉它把你的飞船画在一个新的位置,它就会这样做,而不会触及你之前画的任何其他东西。这很有用,因为它允许您只更新自上次更新以来已更改的那些屏幕部分,而不必每次都绘制所有内容。

      为了让飞船移动,您需要在旧飞船的位置上绘制背景(在您的情况下只是黑色),将飞船移动到新位置,然后在这个新位置重新绘制飞船。

      如果您的宇宙飞船是pygame.sprite.Sprite(意味着它继承自pygame.sprite.Sprite),您可以使用pygame.sprite.Group 来简化整个过程,方法是使用pygame.sprite.Group.clear(screen,background) 在所有Sprite 上绘制背景,然后使用@ 987654326@ 将精灵移动后重新绘制到屏幕上。这在您必须跟踪多个移动对象时特别有用。

      使用您的代码 sn-p 的示例:

      sprites = pygame.sprite.Group(self.spaceship)
      while True:
          for event in pygame.event.get():
              if event.type == pygame.QUIT:
                  sys.exit()
          sprites.clear(self.screen,clear_callback)
          self.spaceship.buttons()
          sprites.draw(self.screen)
          pygame.display.update()
      

      使用这个回调函数(对the documentation稍作修改):

      def clear_callback(surf, rect):
      color = (0, 0, 0)
      surf.fill(color, rect)
      

      这只会重绘屏幕中已更新的部分,从而使重绘非常高效。为了看到这一点,只需将回调函数中的颜色更改为红色。您将看到红色背景仅出现在显示更新的位置。屏幕上保持黑色的每个部分都没有被触摸过。

      除了回调函数,您还可以制作一个与屏幕大小相同的表面,将其填充为黑色,然后将此背景表面用作sprites.clear() 的第二个参数。

      bg = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT))
      bg.fill((0,0,0))
      ...
      while True:
          ...
          sprites.clear(self.screen,bg)
          ...
      

      另外请注意,如果您的游戏变得更复杂并且您必须处理更多 Sprite,您可能需要重新定义您的 spaceship.update() 函数。通常你会将spaceship.buttons()重命名为spaceship.update(),这只会移动飞船的位置,然后使用Spritegroup来处理绘图(而不是让飞船自己绘制,就像你当前的spaceship.update()函数一样) .这将允许您使用pygame.sprite.Group.update() 函数对组中的所有精灵调用更新,使更新循环的绘图部分成为一个简单的调用

      sprites.clear(screen,clear_callback)
      sprites.update()
      sprites.draw(screen)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-11-07
        • 2020-11-07
        • 2015-12-23
        • 2023-01-16
        • 1970-01-01
        • 1970-01-01
        • 2020-04-03
        相关资源
        最近更新 更多