Pygame needs “for event in pygame.event.get()” in order not to crash

匿名 (未验证) 提交于 2019-12-03 01:27:01

问题:

The program works fine like this but, I don't understand why it needs the useless for event in pygame.event.get(): None in the gameOver while statement inside game_loop. If you could find a way to delete it or explain why it doesn't run without it, that would be great!

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

回答1:

Basically, the OS expects pygame to handle events during your program. If the OS notice that events aren't handled, it'll alert the user. The program doesn't actually crash or freeze, the OS is just saying that your program has become unresponsive (which it has because you're not responding to any user events), but it still works.

When your game is entering small scenes you might think that you don't need to handle events, but there is one event you should always check for: the pygame.QUIT event (sent when the user press the close button at the top corner). In your example you're not allowing the user to quit during the game over sequence (you're providing the player a button to click but a user would also expect clicking the close button would close the game as well).

Another reason is that the event queue is constantly filling up. So if the user would spam multiple keys and press multiple areas with the mouse, nothing would happen until he/she enters the game again (where you have an event loop). Then every event would be executed. Therefore it's important to regularly empty the queue. The queue is emptied every time you call pygame.event.get() or pygame.event.clear().

The function pygame.event.pump() is the function that put all events into the event queue (it doesn't clear the previous events, it just adds). The event queue won't be filled/updated with any events if the function isn't called. However, the function is implicitly called inside the functions pygame.event.get(), pygame.event.clear(), pygame.event.poll(), pygame.event.wait() and pygame.event.peek(), so there is rarely a reason to call it explicitly. If you are sure you don't want to handle events at some time, you could use pygame.event.clear() so the event queue is empty when you start processing events again. If you don't want to handle events at all, then use pygame.event.pump().



回答2:

Every process with a GUI needs to maintain a Message Pump (at least in Windows it's critical)

Most of the time, your GUI framework (QT for example) will maintain the pump for you - and will dispatch matching events for your callbacks (mouse clicks, keyboard etc..).

I guess that pygame wants to give you some finer control about how you handle the messages (if I'm not mistaken, game engines would want to wait and pump all events with each rendering of a single frame).



回答3:

You can replace it with pygame.event.pump(). The documentation explains why you need to call this or have to use an event loop each frame.

For each frame of your game, you will need to make some sort of call to the event queue. This ensures your program can internally interact with the rest of the operating system. If you are not using other event functions in your game, you should call pygame.event.pump() to allow pygame to handle internal actions.

This function is not necessary if your program is consistently processing events on the queue through the other pygame.eventpygame module for interacting with events and queues functions.

There are important things that must be dealt with internally in the event queue. The main window may need to be repainted or respond to the system. If you fail to make a call to the event queue for too long, the system may decide your program has locked up.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!