Quick answer: Call pygame.event.get() once per frame, save the list, dispatch from it.

Multiple subsystems each call event.get, draining the queue. Second caller sees empty list. Inputs lost.

The Fix

while running:
    events = pygame.event.get()

    # Pass to subsystems
    ui_manager.handle_events(events)
    player.handle_events(events)
    enemy_ai.handle_events(events)

    # Trim noisy events at startup
    pygame.event.set_allowed([
        pygame.QUIT, pygame.KEYDOWN, pygame.KEYUP,
        pygame.MOUSEBUTTONDOWN, pygame.MOUSEBUTTONUP
    ])

Single get + shared list = no event loss. set_allowed reduces queue overhead by filtering early.

Verifying

Each subsystem sees same events. No dropped key presses.

“One get. Share the list.”

Related Issues

For Clock busy_loop, see Clock busy. For flip vs update, see flip update.

One get. Many readers.