我有一个主循环,可以在某一点更新图像:
循环:
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()
无法清除图像的先前帧?
答案 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()