2

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

dting
  • 38,604
  • 10
  • 95
  • 114
tushortz
  • 3,697
  • 2
  • 18
  • 31

3 Answers3

1

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.

Eli Rose
  • 6,788
  • 8
  • 35
  • 55
1

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
Bartlomiej Lewandowski
  • 10,771
  • 14
  • 44
  • 75
  • Thanks @Bartlomiej Lewandowski I tried this approach before but i still end up in a similar loop because of my code structure – tushortz Jun 08 '15 at 18:21
  • Then change your structure to remove 2 while loops – Bartlomiej Lewandowski Jun 08 '15 at 19:06
  • If i don't use while loops, the code wont run for the duration of time i want it – tushortz Jun 08 '15 at 19:30
  • this is because one while loop is to display the main menu where you can click the play button. When the play button is clicked, another screen is blitted on the surface with a new code running. It wont run because this main game is in a function and when the function is activated, it needs a while loop to continue running. – tushortz Jun 08 '15 at 22:29
  • Try to change your game to be a window state as well. Blit the other screen in draw – Bartlomiej Lewandowski Jun 08 '15 at 22:51
1

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:

Community
  • 1
  • 1
sloth
  • 99,095
  • 21
  • 171
  • 219
  • Thanks the examples were really useful. and ill take a look at the pygame peek first time i came across it – tushortz Jun 11 '15 at 06:47