python pygame

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.