-1

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

Anze
  • 27
  • 6
  • 2
    What is your question? There is no question here. what is the behaviour? what are you experiencing? The question asked is just very poorly. Reread the text and assume I have no idea what is going on . Describe in words what is going on , what you expect and what is happening. something something menu error? is as far as I got. how what? – Jasper Lankhorst Jan 03 '23 at 22:12
  • 1
    @JasperLankhorst Sorry for the unclear question. I edited the post, hopefully it makes more sense now? – Anze Jan 03 '23 at 22:49
  • 1
    That does not help. Please read [ask] and note well that this is **not a discussion forum**. We need each post to be about **one, clear, specific** question. "I'm new to developing with pygame and I ran into a problem that I can't consistently replicate." This already means that you do not yet have a suitable question for Stack Overflow. Before posting, it is your responsibility to figure out specifically what steps are necessary to cause the problem, along with what the problem **is**, and to come up with a clear statement of that problem. – Karl Knechtel Jan 03 '23 at 22:56
  • To get to this point, please also read https://ericlippert.com/2014/03/05/how-to-debug-small-programs/ and [mre] and follow the advice there. – Karl Knechtel Jan 03 '23 at 22:56
  • For example: the problem occurs as a result of spam-clicking some buttons, right? So, what happens if you try taking out the code to handle keyboard input - I assume there's still a problem with the mouse? How about the buttons - do you need to show all of them to cause the problem, or only the ones that will be clicked? How many different ones do you need to click? – Karl Knechtel Jan 03 '23 at 22:58
  • @KarlKnechtel The problem occurs when switching from game to a pause menu by pressing ESC. By doing that the menu opens and the window stops responding. But as mentioned it happens rarely, I can try the same steps like 10000 times and it will happen maybe once or twice. – Anze Jan 03 '23 at 23:14

1 Answers1

0

Since your example is incomplete, it is almost impossible to tell what is causing the problem. However, I have a suspicion that becomes obvious when I carefully read your question and your code:

Last time I ran into the problem was when playing the game normally and then pressing ESC to enter the pause menu. [...]

The code to call the pause menu is very straightforward and followable . However, you do not enter the pause mode immediately, but execute a program logic after the pause mode is activated. I recommend not to execute the program logic if the pause mode was activated immediately before:

while settings.RUNNING:
    settings.EVENTS = pygame.event.get()
    # [...]

    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 not settings.GAME_PAUSED:                         # <---
            if settings.FINISHED:
                settings.FINISHED = False
                level = Level(settings)
            pygame.mixer.music.unpause()
            level.draw()

    elif (settings.GAME_PAUSED):
        # [...]
Rabbid76
  • 202,892
  • 27
  • 131
  • 174