Search code examples
pythonpython-3.xtimepygamesleep

Time.Sleep() is freezing my pygame window and freezing my functions


So i got a big Problem and im researching it since 5 hours without getting anywhere, thats, why im asking here now. at the bottom you can see the Code, where i got my problem. So what it basically does is: it opens an pygame window with 3 buttons: one with start, one with stop and one with quit

when you press start an loop should run, where it plays an sound every x seconds until you press the stop button. the problem is, that the time.sleep() does freeze the whole window. and yes i researched a lot and i didnt came to a conclusion for myself... iam an beginner in python, im doing it for like 2 weeks. Also this is my first post at this Community, so sorry, if this post is different! :p

What i wanna have is, that while the Tonemaker Loop is running, the pygame window stays active and youre able to click the other buttons.

if you need any more informations just ask! Thanks for your Help! Iam really thankful for every answer, because iam really stuck right now.

import pygame, threading
from pygame import *
import time


run = True
distance = int(input("What Distance you wanna Run? [Meters]:"))
timer = int(input("How fast do you wanna Run it? [Seconds]:"))  
frequence = int(input("The Tone should come every? [Meters]:")) 
# Ask all the needed informations and save them as Variables 

tonerepeats = distance / frequence
tonetimer = timer / tonerepeats  # Calculate the time the progam should wait inbetween the sounds
tonetimer = float(tonetimer)  # make the tonetimer an float (number)  important, otherwise sleep will give an error


pygame.init()
displaywidth = 800
displayheight = 800
black = (0, 0, 0)
grey = (30, 30 ,30)
white = (255, 255, 255)              #stuff for the pygame window
red = (200, 0, 0)
green = (0, 200, 0)
brightgreen = (0, 255, 0)
brightred = (255, 0, 0)

gameDisplay = pygame.display.set_mode((displaywidth, displayheight))
pygame.display.set_caption("Tulsa Driller 1.0")
clock = pygame.time.Clock()
tulsaimg = pygame.image.load("D:/python/tulsa.png")


def Tonemaker():                                                #the loop for the playsound function
    while run == True:  # as long as run is true do this
        pygame.mixer.init()  # needed line for playing an sound
        pygame.mixer.music.load("D:/python/sound.wav")  # load up the sound from libarys
        pygame.mixer.music.play(0)  # play the sound (0 = play 1 time) (1= play infinite)
        time.sleep(tonetimer)
          # After playing the sound wait x time till play it again
        clock = pygame.time.Clock()  # needed line for pygame to work
        clock.tick()  # needed line for pygame to work
        while pygame.mixer.music.get_busy():  # avoid errors with the playsound. "while the sound is playing do nothing"
            pygame.event.poll()
            clock.tick()





def tu(x,y):
    gameDisplay.blit(tulsaimg, (x,y))

x = (displaywidth*0.25 )
y = (displayheight*0.25 )

def text_objects(text, font):
    textSurface = font.render(text, True, white)
    return textSurface, textSurface.get_rect()
def button(msg,x,y,w,h,ic,ac,action=None):                 #function for the buttons
    mouse= pygame.mouse.get_pos()
    click= pygame.mouse.get_pressed()


    if x+w > mouse[0] > x and y+h > mouse[1] > y:
        pygame.draw.rect(gameDisplay, ac, (x, y, w, h))
        if click[0] == 1 and action !=None:
            if action == "start": Tonemaker()           # if you press start it starts the loop
            elif action== "stop": run= False            #if you press stop the loop will stop
            elif action== "quit": quit()                #quit the program, when quit button is pressed


    smalltext = pygame.font.Font("freesansbold.ttf", 20)
    textSurf, textRect = text_objects(msg, smalltext)
    textRect.center = ((x + (w / 2)), (y + (h / 2)))
    gameDisplay.blit(textSurf, textRect)



crashed = False

while not crashed:

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            crashed = True



    gameDisplay.fill(grey)
    tu(x, y)

    button("Start",150,650,100,50,green,brightgreen,"start")
    button("Stop", 350, 650, 100, 50, red, brightred,"stop")       #the 3 buttons
    button("Quit", 550, 650, 100, 50, red, brightred,"quit")

    pygame.display.update()
    clock.tick(75)

pygame.quit()
quit()

Solution

  • Here is a way to do it that incorporates the main loop you already have. It checks the time each iteration through the loop. If enough time has elapsed, it calls the Tonemaker() function. (Omitted irrelevant code).

    import time
    
    last_time = None
    # Start the timer
    def StartTone():
        last_time = time.time()
        ToneMaker()
    # Stop the timer
    def StopTone():
        last_time = None
    # Play the sound
    def Tonemaker():
        pygame.mixer.init()  # needed line for playing an sound
        pygame.mixer.music.load("D:/python/sound.wav")  # load up the sound from libarys
        pygame.mixer.music.play(0)  # play the sound (0 = play 1 time) (1= play infinite)
    
    
    while not crashed:
        # Other stuff.....
    
        # Check elapsed time if timer is running
        if last_time != None:
            now = time.time()
            # Has time elapsed?
            if now - last_time >= tonetimer:
                Tonemaker()
                # Reset
                last_time = now