Search code examples
pythonfunctionpygameexitexit-code

Pygame won't quit after calling the function


I'm having some trouble while trying to quit from a function that I made. It just doesn't seem to break the loop. The game opens and I can play around but I can't quit, It just stays there without doing anything and the icon on the task bar goes full yellow.

Here's my code:

import pygame, os, sys, math

black = (0,0,0)
white = (255,255,255)
grey = (128, 128, 128)
gameDisplay = pygame.display.set_mode((800,600))
def game_menu():
    os.environ["SDL_VIDEO_CENTERED"] = "1"
    pygame.init()

    pygame.display.set_caption(".")

    menu = True
    events = pygame.event.get()
    while menu:
        for event in events:
           if event.type == pygame.QUIT:
              menu = False
              pygame.quit()
              quit()


    DISPLAYSURF = pygame.display.set_mode((800, 600))
    DISPLAYSURF.fill(black)

    font = pygame.font.Font('MATRIX.ttf',60)
    TextSurf, TextRect = text_objects("MATRIX PASA PALABRA", font,white)
    TextRect.center = ((600/2),(50))
    gameDisplay.blit(TextSurf, TextRect)
    #Jugar

    button("Jugar",300,200,200,50,None)
    button("Instrucciones",300,275,200,50,None)
    button("Dificultad",300,350,200,50,None)
    button("Salir",300,425,200,50,None)
    pygame.display.update()
def text_objects(text, font,color):
     textSurface = font.render(text, True, color)
      return textSurface, textSurface.get_rect()

def button(msg,x,y,w,h,action=None):
    mouse = pygame.mouse.get_pos()

     events = pygame.event.get()

     if x+w> mouse[0] > (x) and y+h > mouse[1] > y:
        pygame.draw.rect(gameDisplay,grey,(x,y,w,h))
        for event in events:
            if event.type ==pygame.MOUSEBUTTONUP and msg=="Salir":
                pygame.quit()
                quit()
            elif event.type==pygame.MOUSEBUTTONUP and msg=="Jugar":
                None
     else:
          pygame.draw.rect(gameDisplay,white,(x,y,w,h))
          smalltext= pygame.font.Font("MATRIX.ttf",30)
          textsrf,textrct=text_objects(msg,smalltext,black)
          textrct.center = ((x+(w/2)),(y+(h/2)))
          gameDisplay.blit(textsrf,textrct)


if __name__ == "__main__":
   game_menu()

Thanks and sorry for my bad english.


Solution

  • The reason why it doesn't work is that you call pygame.event.get multiple times per frame. The event queue will be emptied after the first call, so the events won't get processed correctly. There should be only one pygame.event.get call per frame.

    To fix this problem, you can assign the list of events that pygame.event.get returns to a variable in the main while loop and then pass it to the button function.

    while menu:
        events = pygame.event.get()
        for event in events:
            # etc.
    
        button("Jugar",300,200,200,50,events,None)
    

    Add an events parameter to the button function:

    def button(msg,x,y,w,h,events,action=None):
        mouse = pygame.mouse.get_pos()
    
        if x+w> mouse[0] > (x) and y+h > mouse[1] > y:
            pygame.draw.rect(gameDisplay,grey,(x,y,w,h))
            for event in events:
                # etc.
    

    BTW, this button function keeps popping up here again and again, probably because it's a really bad way to implement buttons. I'd recommend a solution similiar to one of these: https://stackoverflow.com/a/47664205/6220679 or search for pygame GUI toolkits (SGC is pretty good).


    The others have already mentioned that the indentation in your example is wrong and that sys.exit is a better way to quit than the quit function.

    Here's a fixed, complete example:

    import pygame, os, sys, math
    
    black = (0,0,0)
    white = (255,255,255)
    grey = (128, 128, 128)
    gameDisplay = pygame.display.set_mode((800,600))
    
    
    def game_menu():
        os.environ["SDL_VIDEO_CENTERED"] = "1"
        pygame.init()
    
        pygame.display.set_caption(".")
        DISPLAYSURF = pygame.display.set_mode((800, 600))
        clock = pygame.time.Clock()
    
        menu = True
        while menu:
            events = pygame.event.get()
            for event in events:
               if event.type == pygame.QUIT:
                  menu = False
                  pygame.quit()
                  sys.exit()
    
            DISPLAYSURF.fill((30, 30, 30))
    
            font = pygame.font.Font(None,60)
            TextSurf, TextRect = text_objects("MATRIX PASA PALABRA", font,white)
            TextRect.center = ((600/2),(50))
            gameDisplay.blit(TextSurf, TextRect)
            #Jugar
    
            button("Jugar",300,200,200,50,events,None)
            button("Instrucciones",300,275,200,50,events,None)
            button("Dificultad",300,350,200,50,events,None)
            button("Salir",300,425,200,50,events,None)
            pygame.display.update()
            clock.tick(60)
    
    
    def text_objects(text, font,color):
        textSurface = font.render(text, True, color)
        return textSurface, textSurface.get_rect()
    
    
    def button(msg,x,y,w,h,events,action=None):
        mouse = pygame.mouse.get_pos()
    
        if x+w> mouse[0] > (x) and y+h > mouse[1] > y:
            pygame.draw.rect(gameDisplay,grey,(x,y,w,h))
            for event in events:
                if event.type ==pygame.MOUSEBUTTONUP and msg=="Salir":
                    pygame.quit()
                    sys.exit()
                elif event.type==pygame.MOUSEBUTTONUP and msg=="Jugar":
                    print("jugar")
        else:
            pygame.draw.rect(gameDisplay,white,(x,y,w,h))
            smalltext= pygame.font.Font(None,30)
            textsrf,textrct=text_objects(msg,smalltext,black)
            textrct.center = ((x+(w/2)),(y+(h/2)))
            gameDisplay.blit(textsrf,textrct)
    
    
    if __name__ == "__main__":
       game_menu()