tutorial games example python pygame

python - games - "Pygame.display.update()" no borra la imagen blit



pygame python 3 (2)

Es bastante simple, pygame no hace esto por ti.
pygame.display.update() actualiza toda la escena para mostrar al usuario el nuevo contenido que ha "desactivado". No borra el pasado.

También se puede usar para actualizar solo ciertas áreas donde sabe que ha realizado algunas actualizaciones (para acelerar las cosas).

O bien, haces un flip() para actualizar el búfer gráfico completo para que solo contenga el nuevo contenido que has modificado desde la última vuelta (ten en cuenta que perderás todo lo que no esté en este ciclo):

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

O simplemente "dibuja" una caja negra antes de llamar a la actualización.
Sin embargo, esto es mucho más agotador.

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

Mi recomendación es que use draw_rect y dibuje un rectángulo negro sobre el área anterior donde estaba la nave espacial, o simplemente use flip() para cambiar a una nueva página de búfer en la GPU. Hacer un flip() es extremadamente rápido en la mayoría de las implementaciones.

Vengo de un fondo de Pyglet, por lo que la velocidad de flip() , update() y draw_rect() podría funcionar de manera diferente en Pygame, pero los fundamentos deberían ser los mismos y mi respuesta debería ser válida, si no, por favor indíquelo.

Tengo este ciclo principal que actualiza una imagen en un punto:

El lazo:

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

Donde self.spaceship.buttons() es:

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

Y self.spaceship.update(self.screen) se define:

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

Después de que el bucle principal se actualice, la tecla presiona y "blits" la imagen en la pantalla, se supone que debe actualizar la pantalla ( pygame.display.update() ), pero la pantalla no se borra. Así es como se ve la pantalla, antes y después de mover:

Así es como se ve la imagen antes del blit en una posición diferente

Así es como se ve la imagen después de que la blit está en una posición diferente (después de moverse)

¿Por qué pygame.display.update() no borra los marcos anteriores de la imagen?


Pygame solo dibujará lo que le diga. Si solo le dices que dibuje tu nave espacial en una nueva posición, hará exactamente eso, y no tocará ninguna de las otras cosas que dibujaste previamente. Esto es útil, porque le permite actualizar solo aquellas partes de la pantalla que han cambiado desde su última actualización, sin tener que dibujar todo cada vez.

Para mover la nave espacial, debe dibujar el fondo (en su caso, solo negro) sobre la posición de la nave espacial antigua, mover la nave espacial a su nueva posición y luego volver a dibujar la nave espacial en esta nueva posición.

Si su nave espacial es un pygame.sprite.Sprite (lo que significa que inherts de pygame.sprite.Sprite ), puede usar pygame.sprite.Group para facilitar todo este proceso, utilizando pygame.sprite.Group.clear(screen,background) para dibujar el fondo sobre todos los Sprites y luego usar pygame.sprite.Group.draw(screen) para volver a dibujar los Sprites en la pantalla una vez que se han movido. Esto es especialmente útil una vez que tiene que realizar un seguimiento de más de un objeto en movimiento.

Ejemplo usando su fragmento de código:

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

Con esta función de devolución de llamada (ligeramente modificada de la documentación ):

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

Esto solo redibujará las partes de su pantalla que se han actualizado, haciendo que el redibujado sea muy eficiente. Para ver esto, simplemente cambie el color en la función de devolución de llamada a algo así como rojo. Verá que el fondo rojo solo aparece donde se actualizó la pantalla. No se ha tocado ninguna parte de la pantalla que permanezca negra.

En lugar de la función de devolución de llamada, también puede hacer que una superficie tenga el mismo tamaño que su pantalla, llenarla de negro y usar esta superficie de fondo como su segundo parámetro para sprites.clear() .

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

También tenga en cuenta que si su juego se vuelve más complejo y tiene que manejar más Sprites, es posible que desee redefinir su función spaceship.update() . Por lo general, cambiarías el nombre de spaceship.buttons() a spaceship.update() , que solo movería la posición de la nave espacial, y luego utilizarías el Spritegroup para encargarse del dibujo (en lugar de dibujar la nave espacial como en tu spaceship.update() actual). spaceship.update() ). Esto le permitiría usar la función pygame.sprite.Group.update() para llamar a la actualización en todos los sprites del grupo, haciendo que la parte de dibujo del bucle de actualización sea una simple llamada de

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