pygame levels organisation and running functions one at a time

437 views Asked by At

I made a game but I have two screens to display, the menu page and the game page. On the menu page when i click on a play button, it shows the game without any problem but when i close the running game, it goes back to the menu screen but i want both screens to exit.

Please any help would be greatly appreciated.

sample code:

menu screen

def menu():
    running = True

    while running:
        screen.blit(intros, (0,0))
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False

        GUI.button("Play game", 24,300, 128,50, violet, blue, screen, MAIN)
        necessary things here!

def MAIN():
    running = True

    while running:
        screen.blit(intros, (0,0))
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False

        all action starts here

please can anyone give me a suggestion as to how to run the menu game so that when the play button is clicked and the MAIN code is running, when i click close, the game stops and doesn't return to the menu code.

I've read on several forums on using if __name__ = "__main__" but i find it useless maybe perhaps i don't know how to implement it correctly

3

There are 3 answers

0
Eli Rose On

This is happening because you have two while-loops. Setting running = False exits only the current while-loop, so you leave MAIN only to end up back at menu which you called it from.

If you want setting running = False to exit out of both loops, make it a global variable (and have only one of it).

running = True
def menu():
    ...
def MAIN():
    ...

You could also use import sys and sys.exit() if you want to completely quit the program. But I recommend the first one.

5
Bartlomiej Lewandowski On

It's a good time to split up your code. I would recommend you to have only one loop. Look into the State pattern.

What you need is a single class that will call the functions in your screens at the right moments. I'll make a draft here that you can then continue.

class Window:
    def __init__(self):
        self.state = Menu()
        self.screen = initPygame()
    def run():
        self.state.draw(self.screen)
        self.state.update()
        for event in pygame.event.get():
            self.state.handleEvent(event) 
            if event.type == pygame.QUIT:
                running = False

class Menu:
    def __init__(self):
        pass
        #initialize all menu things (images etc)
    def handleEvent(self, event):
        #change state caused by event
        pass
    def draw(self, screen):
        pass
    def update(self):
        #called once per frame
        pass
1
sloth On

A simple solution that does not change much in your code is to simply use peek to look for the QUIT event without removing it from the event queue:

def MAIN():
    while True:
        screen.blit(intros, (0,0))
        if pygame.event.peek(pygame.QUIT):
            # since we're in a function, we can simply use return
            return
        for event in pygame.event.get():
            # handle other events

        #all action starts here

Another way would be to post the QUIT event again yourself with pygame.event.post:

def MAIN():
    while True:
        screen.blit(intros, (0,0))
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.event.post(pygame.QUIT)
                # since we're in a function, we can simply use return
                return 

        #all action starts here

but that's a little bit ugly although it makes sure the event bubbles up to the menu loop.


The best solution IMHO, which would require you to rewrite a large chunk of your code, is to use a single main loop and a state to decide what scene (menu or gameplay) you're acutally handling at the moment.

Take a look at these questions/answers for inspiration: