python - Pygame necesita "para el evento en pygame.event.get()" para no bloquearse
(3)
Básicamente, el sistema operativo espera que pygame maneje eventos durante su programa. Si el sistema operativo nota que los eventos no se manejan, alertará al usuario. El programa en realidad no se bloquea ni se congela, el sistema operativo solo está diciendo que su programa no responde (lo que sucede porque no responde a ningún evento del usuario), pero aún funciona.
Cuando su juego ingresa a escenas pequeñas, puede pensar que no necesita manejar eventos, pero hay un evento que siempre debe verificar: el evento
pygame.QUIT
(enviado cuando el usuario presiona el botón de cierre en la esquina superior) .
En su ejemplo, no está permitiendo que el usuario salga durante la secuencia del juego (le está dando al jugador un botón para hacer clic, pero un usuario también esperaría que al hacer clic en el botón Cerrar también se cierre el juego).
Otra razón es que la cola de eventos se está llenando constantemente.
Por lo tanto, si el usuario enviara varias teclas y presionara múltiples áreas con el mouse, no pasaría nada
hasta
que vuelva a ingresar al juego (donde tiene un bucle de eventos).
Entonces
cada
evento sería ejecutado.
Por lo tanto, es importante vaciar regularmente la cola.
La cola se vacía cada vez que llama a
pygame.event.get()
o
pygame.event.clear()
.
La función
pygame.event.pump()
es la función que coloca todos los eventos en la cola de eventos (no borra los eventos anteriores, solo agrega).
La cola de eventos no se completará / actualizará con ningún evento si no se llama a la función.
Sin embargo, la función se llama implícitamente dentro de las funciones
pygame.event.get()
,
pygame.event.clear()
,
pygame.event.poll()
,
pygame.event.wait()
y
pygame.event.peek()
, así que rara vez hay una razón para llamarlo explícitamente.
Si está seguro de que no desea manejar eventos en algún momento, puede usar
pygame.event.clear()
para que la cola de eventos esté vacía cuando comience a procesar eventos nuevamente.
Si no desea manejar eventos en absoluto, use
pygame.event.pump()
.
El programa funciona bien así, pero no entiendo por qué necesita el
for event in pygame.event.get(): None
inútil
for event in pygame.event.get(): None
en la declaración
gameOver
while dentro de
game_loop
.
Si pudiera encontrar una manera de eliminarlo o explicar por qué no funciona sin él, ¡sería genial!
import pygame, time, random
pygame.init()
# SOUND/TEXTURES
icon = pygame.image.load("textures/snakeicon.png")
pygame.display.set_icon(icon)
# VARIABLES
white = (255, 255, 255)
black = (0, 0, 0)
red = (200, 0, 0)
green = (0, 155, 0)
bright_green = (0, 250, 0)
bright_red = (255, 0, 0)
font_size = 50
font = pygame.font.SysFont(None, font_size)
# FUNCTIONS
def text_objects(text, font):
textSurface = font.render(text, True, black)
return textSurface, textSurface.get_rect()
def button(msg, x, y, w, h, ic, ac, action=None):
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
if x + w > mouse[0] > x and y + h > mouse[1] > y:
pygame.draw.rect(gameWindow, ac, (x, y, w, h))
if click[0] == 1 and action != None:
if action == "play":
game_loop()
elif action == "quit":
gameRun = False
gameWindow.fill(white)
message_to_screen("Closing Game...", black, 280, 280)
pygame.display.update()
time.sleep(1)
pygame.quit()
quit()
else:
pygame.draw.rect(gameWindow, ic, (x, y, w, h))
smallText = pygame.font.Font("freesansbold.ttf", 20)
textSurf, textRect = text_objects(msg, smallText)
textRect.center = ((x + (w / 2)), (y + (h / 2)))
gameWindow.blit(textSurf, textRect)
def snake(rect_x, rect_y, block_size):
pygame.draw.rect(gameWindow, green, [rect_x, rect_y, block_size, block_size])
def message_to_screen(msg, color, x, y):
screen_text = font.render(msg, True, color)
gameWindow.blit(screen_text, [x, y])
# WINDOW/SURFACE
display_w = 800
display_h = 600
window_title = "Window"
gameWindow = pygame.display.set_mode((display_w, display_h))
pygame.display.set_caption(window_title)
# FPS/Clock
clock = pygame.time.Clock()
# Game Loop
def game_loop():
# RECT OPTIONS
moveSpeed = 10
block_size = 10
rect_x = display_w / 2
rect_y = display_h / 2
change_x = 0
change_y = 0
randApplex = round(random.randrange(0, display_w - block_size) / 10.0) * 10.0
randAppley = round(random.randrange(0, display_h - block_size) / 10.0) * 10.0
global gameRun, gameOver
gameRun = True
gameOver = False
while gameRun:
while gameOver:
gameRun = False
gameWindow.fill(white)
# button(msg, x, y, w, h, ic, ac, action=None)
message_to_screen("Game Over!", red, 300, 300)
button("Restart", 150, 450, 100, 50, green, bright_green, "play")
button("Quit", 550, 450, 100, 50, red, bright_red, "quit")
pygame.display.update()
# RIGHT HERE!
for event in pygame.event.get():
None
# RIGHT THERE!
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameRun = False
gameOver = False
gameWindow.fill(white)
message_to_screen("Closing Game...", black, 280, 280)
pygame.display.update()
time.sleep(1)
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
change_y = -moveSpeed
change_x = 0
elif event.key == pygame.K_s:
change_y = moveSpeed
change_x = 0
elif event.key == pygame.K_a:
change_x = -moveSpeed
change_y = 0
elif event.key == pygame.K_d:
change_x = moveSpeed
change_y = 0
# BOARDER CRASH
if rect_x >= display_w or rect_x < 0 or rect_y >= display_h or rect_y < 0:
gameOver = True
# LOGIC
rect_x += change_x
rect_y += change_y
if rect_x == randApplex and rect_y == randAppley:
randApplex = round(random.randrange(0, display_w - block_size) / 10.0) * 10.0
randAppley = round(random.randrange(0, display_h - block_size) / 10.0) * 10.0
# RENDER
gameWindow.fill(white)
pygame.draw.rect(gameWindow, red, [randApplex, randAppley, block_size, block_size])
snake(rect_x, rect_y, block_size)
pygame.display.update()
clock.tick(15)
message_to_screen("You Lose!", red, 325, 300)
pygame.display.update()
time.sleep(1)
message_to_screen("Closing Game!", black, 280, 350)
pygame.display.update()
time.sleep(1)
# QUIT
pygame.quit()
quit()
game_loop()
Cada proceso con una GUI necesita mantener una bomba de mensajes (al menos en Windows es crítico)
La mayoría de las veces, su marco GUI (QT, por ejemplo) mantendrá la bomba por usted y enviará eventos coincidentes para sus devoluciones de llamada (clics del mouse, teclado, etc.).
Supongo que
pygame
quiere darte un control más
pygame
sobre cómo manejas los mensajes (si no me equivoco, los motores de juego querrían esperar y bombear todos los eventos con cada representación de un solo cuadro).
Puede reemplazarlo con
pygame.event.pump()
.
La documentación explica por qué necesita llamar a esto o usar un bucle de eventos en cada cuadro.
Para cada cuadro de tu juego, deberás hacer algún tipo de llamada a la cola del evento. Esto garantiza que su programa pueda interactuar internamente con el resto del sistema operativo. Si no está utilizando otras funciones de eventos en su juego, debe llamar a pygame.event.pump () para permitir que pygame maneje acciones internas.
Esta función no es necesaria si su programa procesa constantemente eventos en la cola a través del otro módulo pygame.eventpygame para interactuar con eventos y funciones de colas.
Hay cosas importantes que deben tratarse internamente en la cola de eventos. Es posible que sea necesario volver a pintar la ventana principal o responder al sistema. Si no realiza una llamada a la cola de eventos durante demasiado tiempo, el sistema puede decidir que su programa se ha bloqueado.