Creating your own user events in pygame
If you are making a game with pygame you'll find that often you will use a pattern where the Pygame event loop effectively powers your game.
For example say you were rendering some text and you wanted someone to be able to change that text via the terminal. One way you could do this is to have the terminal input running in a thread then synchronize state with the Pygame font renderer via some form of shared variable.
There's a lot of downsides to this approach though, and an easier way is to make use of user defined pygame events like so:
import threading
import pygame
import pygame.freetype
pygame.init()
UPDATE_FROM_TERMINAL = pygame.USEREVENT + 1
FONT = pygame.freetype.SysFont("Arial", 48)
font_coords = [40, 300]
text = "Hello world!"
COLOR_WHITE = (255, 255, 255)
screen_resolution = (1024, 768)
screen = pygame.display.set_mode(size=screen_resolution)
def text_changer():
while True:
new_text = input("New text:")
evt = pygame.event.Event(UPDATE_FROM_TERMINAL, text=new_text)
pygame.event.post(evt)
text_update_thread = threading.Thread(target=text_changer)
text_update_thread.start()
while True:
for event in pygame.event.get():
screen.fill(COLOR_WHITE)
if event.type == pygame.QUIT:
pygame.quit()
if event.type == UPDATE_FROM_TERMINAL:
text = event.text
FONT.render_to(surf=screen, dest=font_coords, text=text, fgcolor=(128, 255, 255))
pygame.display.flip()
text_update_thread.join()
pygame.quit()
This has the benefit of keeping all of your logic in the same spot and can help you avoid some potential concurrency state management issues.
Full source code for this proof of concept can be found here: https://github.com/shuttle1987/pygame-event-loop