" pygame.display.update()"不清楚blit图像

时间:2016-06-08 14:28:20

标签: python pygame

我有一个主循环,可以在某一点更新图像:

循环:

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))

主循环更新后按键和" blits"将图像添加到屏幕上,应该更新显示(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()无法清除图像的先前帧?

2 个答案:

答案 0 :(得分:2)

这很简单,pygame不会为你做这件事 pygame.display.update()更新整个场景,向用户显示新内容您已“眨眼”。它不会抹去过去。

它还可以用于仅更新您知道已完成更新的某些区域(以加快速度)。

或者,您执行flip()更新整个图形缓冲区,只包含自上次翻转后您已经闪过的新内容(请注意,您将丢失此循环中的所有内容):

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

或者,你只需在调用更新之前“画”一个黑盒子 然而,这更加沉重。

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

我的建议是你要么使用draw_rect并在太空船所在的上一个区域上绘制一个黑色矩形,要么只是使用flip()交换到GPU中的新缓冲页面。在大多数实现中,执行flip()非常快。

我来自Pyglet背景,因此flip()update()draw_rect()的速度表现可能在Pygame中有所不同,但基本原理应该相同,我的回答应该是有效,如果不是,请指出这一点。

答案 1 :(得分:1)

Pygame只会绘制你告诉它的东西。如果你只是告诉它将你的宇宙飞船拉到一个新的位置,它就会做到这一点,而不是触及你之前绘制的任何其他东西。这很有用,因为它允许您仅更新自上次更新以来已更改的屏幕部分,而无需每次都绘制所有内容。

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

如果您的太空船是pygame.sprite.Sprite(意思是来自pygame.sprite.Sprite的inherts),您可以使用pygame.sprite.Group来简化整个过程,方法是使用pygame.sprite.Group.clear(screen,background)绘制所有Sprite上的背景,然后使用pygame.sprite.Group.draw(screen)将Sprite重新绘制到屏幕上。一旦必须跟踪多个移动物体,这一点尤其有用。

使用您的代码段的示例:

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)
    ...

另请注意,如果您的游戏变得更复杂并且您必须处理更多精灵,则可能需要重新定义spaceship.update()功能。通常你会将spaceship.buttons()重命名为spaceship.update(),这只会移动宇宙飞船的位置,然后使用精灵组来处理绘图(而不是像现在一样在宇宙飞船上画画) {1}}功能)。这将允许您使用spaceship.update()函数调用组中所有精灵的更新,使更新循环的绘图部分简单地调用

pygame.sprite.Group.update()