简体   繁体   中英

How to end a loop, from outside the loop in python

I am making a pygame game with python 3.8.3, In my game I have a starting screen, that is inside this while loop:

def game_intro(): 
    intro = True 
    mixer.music.load("musicIntro.mp3")
    mixer.music.set_volume(0.02) 
    mixer.music.play(-1) 
    while intro:
        for event in pygame.event.get():
            if event.type == pygame.QUIT: 
                pygame.quit()
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RETURN:
                    intro = False
        screen.blit(startscherm_img, bordrect) 
        clock.tick(30)
        button("Start",302,517,94,44,donkerOranje,lichtOranje,"start")
        button("Music",553,517,94,44,donkerOranje,lichtOranje,"toggleMusic")
        button("Quit",803,517,94,44,donkerOranje,lichtOranje,"quit")
        pygame.display.flip() 
game_intro()

I am calling for my button function that I have defined above:

def button(msg,x,y,w,h,ic,ac,action=None): 
    mousePos = pygame.mouse.get_pos() 
    click = pygame.mouse.get_pressed() 
    if x+w > mousePos[0] > x and y+h > mousePos[1] > y: 
        pygame.draw.rect(screen, ac, (x,y,w,h)) 
        if click[0] == 1 and action != None: 
            if action == "toggleMusic": 
                PAUSE.toggle()
                time.sleep(0.3)
            elif action == "quit": 
                pygame.quit()
                time.sleep(0.3)
            elif action == "start": 
                time.sleep(0.3)
                intro = False
    else:
        pygame.draw.rect(screen, ic, (x,y,w,h)) 

    smallText = pygame.font.SysFont("Bauhaus 93",30)
    textSurf, textRect = text_objecten(msg, smallText)
    textRect.center = ( (x+(w/2)), (y+(h/2)) )
    screen.blit(textSurf, textRect)

It basically just checks for mouse clicking within a certain area, and if it detects that it executes code.

Now on my starting screen I have a button start, I would like it to end the game_intro() loop, however trying intro = False does not result in anything. trying break does not work, as it would have to be in the loop itself.

So my question is: How do I make this start button actually end the game_intro() loop?

PS I am quite new to Python

As far as I can see, you are setting intro = False inside the function button , but you also have a variable named intro inside the game_intro function. Eventhough they have the same name, Python treats them as distinct variables.

In order to make effective the change on the intro variable from one function to the other, you need to either set the intro variable as global, or to pass the intro variable as a parameter between the two functions.

Option 1:

intro = True

def button(msg,x,y,w,h,ic,ac,action=None): 
    global intro
    mousePos = pygame.mouse.get_pos() 
    click = pygame.mouse.get_pressed() 
    if x+w > mousePos[0] > x and y+h > mousePos[1] > y: 
        pygame.draw.rect(screen, ac, (x,y,w,h)) 
        if click[0] == 1 and action != None: 
            if action == "toggleMusic": 
                PAUSE.toggle()
                time.sleep(0.3)
            elif action == "quit": 
                pygame.quit()
                time.sleep(0.3)
            elif action == "start": 
                time.sleep(0.3)
                intro = False

def game_intro(): 
    global intro
    mixer.music.load("musicIntro.mp3")
    mixer.music.set_volume(0.02) 
    mixer.music.play(-1) 
    while intro:
        for event in pygame.event.get():
            if event.type == pygame.QUIT: 
                pygame.quit()
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RETURN:
                    intro = False
        screen.blit(startscherm_img, bordrect) 
        clock.tick(30)
        button("Start",302,517,94,44,donkerOranje,lichtOranje,"start")
        button("Music",553,517,94,44,donkerOranje,lichtOranje,"toggleMusic")
        button("Quit",803,517,94,44,donkerOranje,lichtOranje,"quit")
        pygame.display.flip() 
game_intro()

Option 2:

def button(msg,x,y,w,h,ic,ac, intro, action=None): 
    mousePos = pygame.mouse.get_pos() 
    click = pygame.mouse.get_pressed() 
    if x+w > mousePos[0] > x and y+h > mousePos[1] > y: 
        pygame.draw.rect(screen, ac, (x,y,w,h)) 
        if click[0] == 1 and action != None: 
            if action == "toggleMusic": 
                PAUSE.toggle()
                time.sleep(0.3)
            elif action == "quit": 
                pygame.quit()
                time.sleep(0.3)
            elif action == "start": 
                time.sleep(0.3)
                intro = False
    return intro

def game_intro(): 
    intro = True
    mixer.music.load("musicIntro.mp3")
    mixer.music.set_volume(0.02) 
    mixer.music.play(-1) 
    while intro:
        for event in pygame.event.get():
            if event.type == pygame.QUIT: 
                pygame.quit()
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RETURN:
                    intro = False
        screen.blit(startscherm_img, bordrect) 
        clock.tick(30)
        intro = button("Start",302,517,94,44,donkerOranje,lichtOranje,intro,"start")
        intro = button("Music",553,517,94,44,donkerOranje,lichtOranje,intro,"toggleMusic")
        intro = button("Quit",803,517,94,44,donkerOranje,lichtOranje,intro,"quit")
            pygame.display.flip() 
game_intro()

You can do some OOP. Try creating it inside a class like this:

class Intro:

  def __init__(self):
    self.intro = True

  def game_intro(self): 
    mixer.music.load("musicIntro.mp3")
    mixer.music.set_volume(0.02) 
    mixer.music.play(-1) 
    while self.intro:
        for event in pygame.event.get():
            if event.type == pygame.QUIT: 
                pygame.quit()
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RETURN:
                    self.intro = False
        screen.blit(startscherm_img, bordrect) 
        clock.tick(30)
        button("Start",302,517,94,44,donkerOranje,lichtOranje,"start")
        button("Music",553,517,94,44,donkerOranje,lichtOranje,"toggleMusic")
        button("Quit",803,517,94,44,donkerOranje,lichtOranje,"quit")
        pygame.display.flip() 

  def button(self, msg,x,y,w,h,ic,ac,action=None): 
    mousePos = pygame.mouse.get_pos() 
    click = pygame.mouse.get_pressed() 
    if x+w > mousePos[0] > x and y+h > mousePos[1] > y: 
        pygame.draw.rect(screen, ac, (x,y,w,h)) 
        if click[0] == 1 and action != None: 
            if action == "toggleMusic": 
                PAUSE.toggle()
                time.sleep(0.3)
            elif action == "quit": 
                pygame.quit()
                time.sleep(0.3)
            elif action == "start": 
                time.sleep(0.3)
                self.intro = False


obj = Intro()
start = obj.gameintro()

The intro is defined inside an instance using self so it can be called anywhere inside the class.

All though I have not done python in a while you could try running your loop as a new thread then kill it once finish as a thread manually in all honesty setting intro to false should have worked I would do some debugging first to actually check if intro is being set to false. Although upon reading your code further I noticed that you actually call the function game_intro() twice which would cause you to loop as the variable intro is defined in side of the function so calling the function game_intro() would reset the loop so maybe remove the calling at the end since you already have it in a while loop. Another option is to define the variable intro out side of the function cheers

Threading Events

Assign a global scope variable (outside the two functions) as a threading.Event instance.

Then, set and clear that event when you want to control the loop.

import threading


do_intro_loop = threading.Event


def button(action=None):
  if action == "start":
    do_intro_loop.clear()

def into():
  do_intro_loop.set()
  while do_intro_loop.is_set():
    # show do intro stuff here
    pass

intro()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM