I'm new to developing with pygame and I ran into a problem that I can't consistently replicate. I have a suspicion that the problems occurs somewhere in menu handling, but I can't pinpoint the problem. I ran into the problem the most times if I spammed buttons in menu (tried stress testing) and sometimes when pausing the game.
EDIT:
To clarify the problem a bit more. I strongly suspect that the problem occurs while handling menu states. The code and the game works as intended and perfectly fine for 99% of the time, but in that 1% the window freezes and stops responding. Next two scenarios are the ones that occured the most.
Scenario 1: Last time I ran into the problem was when playing the game normally and then pressing ESC to enter the pause menu. Game froze and stopped responding. Expected result: Pause menu opens, without causing the game to stop responding and you can resume the game, access settings or go back to main menu from the menu (The correct scenario occurs 99% of the time).
Scenario 2 (happend in the past doesn't anymore): In the past I also ran into the same problem while stress testing menus, by fast switching between them, the game also froze and stopped responding, but I later added cooldown to limit the speed and ensure everything was loaded properly and haven't had problems with this scenario ever since.
So the problem is game randomly freezes and stops responding and the problem is really random and I can't get to the point where I can consistantly replicate it, I can do the same thing (play the game and go to the pause menu) a thousand times and it will work fine, but then one time it will just stop responding. So the question in short is did I forgot to check for something or if i forgot to add something while handling different menus, because like i said im new to pygame and don't know how everything works. And again the problem is really hard to replicate and pinpoint what exactly happens, it usually takes me 30 min of trying to make it happen again.
Game loop:
while settings.RUNNING:
settings.EVENTS = pygame.event.get()
if (settings.MUSIC_MUTED):
pygame.mixer.music.set_volume(0)
else:
pygame.mixer.music.set_volume(int(settings.MUSIC_VOLUME) / 100)
if not (settings.GAME_PAUSED):
for event in settings.EVENTS:
if event.type == pygame.QUIT:
settings.RUNNING = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
settings.MENU_STATE = 'pause'
pause_start = pygame.time.get_ticks()
settings.MENU_CD = pygame.time.get_ticks()
settings.GAME_PAUSED = True
if settings.FINISHED:
settings.FINISHED = False
level = Level(settings)
pygame.mixer.music.unpause()
level.draw()
elif (settings.GAME_PAUSED):
#Some other code
pygame.display.update()
GAME_CLOCK.tick(60)
pygame.quit()
sys.exit()
Pause part event handling:
for event in settings.EVENTS:
if event.type == pygame.QUIT:
settings.RUNNING = False
if settings.MENU_STATE == "main":
if event.type == pygame_gui.UI_TEXT_ENTRY_CHANGED and event.ui_object_id == "#name_input_field" and (pygame.time.get_ticks() - settings.MENU_CD) >= 175:
settings.PLAYER_NAME = event.text
NAME_INPUT.process_events(event)
if settings.MENU_STATE == "keybinds" and waiting_input:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
if waiting_for == "left":
left_button.image = settings.MENU_ASSETS["buttons"]["button"]
if waiting_for == "right":
right_button.image = settings.MENU_ASSETS["buttons"]["button"]
if waiting_for == "jump":
jump_button.image = settings.MENU_ASSETS["buttons"]["button"]
waiting_for = ""
waiting_input = False
elif event.key not in [settings.KEYBINDS['left'], settings.KEYBINDS['right'], settings.KEYBINDS['jump']]:
if waiting_for == "left":
save_settings({
'left' : event.key,
'right': settings.KEYBINDS['right'],
'jump': settings.KEYBINDS['jump']
})
left_button.image = settings.MENU_ASSETS["buttons"]["button"]
elif waiting_for == "right":
save_settings({
'left' : settings.KEYBINDS['left'],
'right': event.key,
'jump': settings.KEYBINDS['jump']
})
right_button.image = settings.MENU_ASSETS["buttons"]["button"]
elif waiting_for == "jump":
save_settings({
'left' : settings.KEYBINDS['left'],
'right': settings.KEYBINDS['right'],
'jump': event.key
})
jump_button.image = settings.MENU_ASSETS["buttons"]["button"]
set_keybinds(settings)
waiting_input = False
waiting_for = ""
One of the menus (the one where the problem occured latest):
if (settings.MENU_STATE == 'pause'):
print("pause menu", settings.GAME_PAUSED, settings.RUNNING)
pygame.mixer.music.pause()
title_image = pygame.image.load('./assets/menu/title/title.png').convert_alpha()
SCREEN.blit(title_image, ((settings.SCREEN_WIDTH/2 - title_image.get_width()/2),(settings.SCREEN_HEIGHT/4 - title_image.get_height() * 3 / 4)))
if resume_button.draw(SCREEN) and (pygame.time.get_ticks() - settings.MENU_CD) >= 175:
settings.GAME_PAUSED = False
level.pause_time += (pygame.time.get_ticks() - pause_start)
pause_start = 0
continue
if settings_button.draw(SCREEN) and (pygame.time.get_ticks() - settings.MENU_CD) >= 175:
settings.PREVIOUS_MENU = "pause"
settings.MENU_STATE = "settings"
settings.MENU_CD = pygame.time.get_ticks()
continue
if mainmenu_button.draw(SCREEN) and (pygame.time.get_ticks() - settings.MENU_CD) >= 175:
settings.MENU_STATE = "main"
settings.MENU_CD = pygame.time.get_ticks()
continue
Additional info if needed: My python version is 3.9.13. For any additional code references, that you think you might need, the whole code is available on: github link