Pygame another thread not getting QUIT event? - python

I'm making an game for ending my programming course and I sometimes have some longer scenes displayed and the loop ain't checking for if there is QUIT event and then stop everything and close the loop. So I thought multi-threading would help, but apparently it doesn't seem to get events, I have tried printing out - it gets events, but it simply aint getting QUIT event.
Here is the code:
from pygame import *
from threading import Thread
def closesearcher():
global running
while running:
for i in event.get():
if i.type == QUIT:
print ("QUIT event in closesearcher")
running = False
quit()
exit()
clock.tick(60)
def main():
init()
#True while game is running
global running
running = True
global window
window = display.set_mode([640, 480])
global clock
clock = time.Clock()
#Let's start closesearcher
searcherclose = Thread(target = closesearcher)
searcherclose.start()
scenegame = gamescene()
def gamescene():
#Render some scenery, wait for user to press button, etc in the following loop
while running:
for i in event.get():
if i.type == QUIT:
print ("QUIT event in game loop")
clock.tick(60)
if __name__ == "__main__":
main()
Any solutions that would be similiar to the structure of my current code?
Note: I use Python 3.2

How about actually exiting the loops with return instead of only printing that you got the quit event?
Currently, you only exit the loop in closesearcher but not in gamescene.
Also, I think event.get() will remove the event. So calling get in the other loop will not return anything. You need to set a global flag playerWantsToQuit and use that instead of the local running variables.

Related

How can I play another music list with Pygame? [duplicate]

I am looking to iterate through a list of songs such as Songs = ["Song1.mp3", "Song2.mp3", "Song3.mp3"] and I want to play each song one after each other.
I have tried various methods, the most suggested seemed to use pygame, however, I have not been able to debug the tremendous amount of errors that come with using it. My main source code and attempt at this is as shown below:
from tkinter import *
import pygame
from random import choice
import os
pygame.mixer.init()
Songs = os.listdir("Music\\")
def Play():
Song = choice(Songs)
pygame.mixer.music.load("Music\\" + Song)
pygame.mixer.music.play()
while True:
play()
Upon running this I receive error pygame.error: ModPlug_Load failed.
I am running this concurrently inside of a slideshow program I have, I want this code to run as background music and I plan on checking for the end of the song in a Function I already have set.
Use pygame.mixer.music.get_busy() to detect if a music stream is actively playing. Play the next song from the list when no stream is active. e.g:
import pygame
play_list = ["song1.mp3", "song2.mp3", "song3.mp3"]
current_list = []
pygame.init()
clock = pygame.time.Clock()
run = True
while run:
clock.tick(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if not pygame.mixer.music.get_busy():
if not current_list:
current_list = play_list[:]
current_song = current_list.pop(0)
pygame.mixer.music.load(current_song)
pygame.mixer.music.play()
pygame.quit()
exit()
You can register a custom event which will be triggered when the music is done playing using pygame.mixer.music.set_endevent().
Also you need to run the while loop in a child thread if you want to run concurrently with main application.
Below is an example:
import os
import random
import threading
import tkinter as tk
import pygame
pygame.init()
# create a custom event
MUSIC_DONE = pygame.event.custom_type()
# register the event
pygame.mixer.music.set_endevent(MUSIC_DONE)
folder = "Music\\"
Songs = os.listdir(folder)
def next_song():
try:
song = random.choice(Songs)
pygame.mixer.music.load(os.path.join(folder, song))
pygame.mixer.music.play()
# update song name
song_var.set(song)
except Exception as e:
print(e)
def pygame_loop():
next_song()
while pygame.get_init():
for event in pygame.event.get():
if event.type == MUSIC_DONE:
# current song done playing, play next song
next_song()
root = tk.Tk()
# label to show the current song being played
song_var = tk.StringVar()
tk.Label(root, textvariable=song_var).pack()
# start the pygame loop in a child thread
threading.Thread(target=pygame_loop).start()
root.mainloop()
# quit pygame
pygame.quit()
If it's a desktop app, you have multiple options to play a file, usually, it depends:
Also to avoid Tkinter being stuck, you need to use threads or multiprocess. I recommend you soundfile player, you will find examples here https://realpython.com/playing-and-recording-sound-python/

Pygame mainloop qiuting exception handling

Hi I am writing a simple chess program, unfortunately I have run in some unexpected problems, namely. After I added a list which keeps track of all the figures positions, I cannot close the window using the method which I till now used. which was:
for event in pygame.event.get():
# print(event)
# Checking if the user clicks the red quit cross
if event.type == pygame.QUIT:
# run control the mainloop, wheather True or not
run = False
After adding the list, this stopped working, so I use now:
for event in pygame.event.get():
# print(event)
if event.type == pygame.QUIT:
pygame.display.quit()
pygame.quit()
I tried to add some exception handling:
try:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.display.quit()
except pygame.error():
print('Program closed')
However the except statement is not reached and an error is printed: (pygame.error: video system not initialized)
Can You please tell me how to handle this exception properly, or suggest a different way of braking the mainloop.
remove the () from the exception catching, namely:
except pygame.error instead of except pygame.error()
I acctually figured it out on my own, so just in case someone is looking for the anwser. The issue was that I was trying to call the redraw function after pygame.display.quit(). Thus after moving both the redraw call and the keys = pygame.key.get_pressed() [wich also utilises the module pygame] the program terminates without any error call. The code should look as follows:
while run:
pygame.time.delay(100)
window_redrawing()
# Gathering user keyboard input
keys = pygame.key.get_pressed()
# making sure the window can be closed
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.display.quit()
run = False
fig_pos.clear()

How to close the pygame window without using quit()/sys.exit() so that I don't quit the loop outside of the game?

I am creating a chat system and want to insert a game made with Pygame. In the state_machine file of the chat system, I set a state of the client as S_GAMING. When the client type "game" in the S_LOGGEDIN state, the state will be changed into S_GAMING and when the game is over, the user can quit the game either by clicking the "x" button or by waiting for 3 seconds.
I have some trouble closing the game window without exiting the chat system.
when I used pygame.quit(), the window will froze.
When I tried pygame.quit() and sys.exit() or quit(), I exited the chat system as well.
This is a part of the game.py file:
run = True
gameOver = False
timer = 0
while run:
clock.tick(27)
#check events
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if not gameOver:
drawWindow()
for each in barriers:
if each.isHit:
gameOver = True
else:
if timer < 81:
win.blit(game_over,(0,0))
timer +=1
pygame.display.update()
else:
run = False
pygame.display.quit()
pygame.quit()
This is a part of the chat_state_machine file:
elif self.state == S_GAMING:
import game
self.state = S_LOGGEDIN
I know this is a specific question and I can provide more code if the above is not clear.
Hopefully, I can get an answer. I am all ears.
Here is a simple solution: Once you exit pygame the code should throw an exception, in that case you can switch run to False and start a new loop
import pygame
pygame.init()
screen = pygame.display.set_mode((600, 400))
clock = pygame.time.Clock()
run = True
while run:
try:
screen.fill((0,0,0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
clock.tick(120)
pygame.display.update()
except:
run = False
while not run:
#Your other code here
pass

Python: Why is pygame.event.key.get_pressed() not working?

I have been trying to make it where if i press space when the program has already been launched it will play my song.
It opens up, then i get the loading animation on my cursor(when cursor is over the program.).The programs crashed.
`import pygame, sys
from pygame.locals import *
bf = 'bg.jpg'
pygame.init()
screen = pygame.display.set_mode((800, 600))
background = pygame.image.load(bf) .convert()
screen.blit(background, (0,0))
pygame.display.update()
pygame.display.set_caption('Letters')
keys=pygame.key.get_pressed()
while True:
if keys[pygame.K_SPACE]:
pygame.mixer.music.load('ht.mp3')
pygame.mixer.music.play(loops=-1, start=0)
running = True
while running:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
Please explain it me like I was a kid.(I am new in pygame.)
Your program is stuck here:
while True:
if keys[pygame.K_SPACE]:
pygame.mixer.music.load('ht.mp3')
pygame.mixer.music.play(loops=-1, start=0)
The loop never ends. Once you obtain the condition you needed, you should break the loop:
while True:
if keys[pygame.K_SPACE]:
pygame.mixer.music.load('ht.mp3')
pygame.mixer.music.play(loops=-1, start=0)
break
Or just remove the while loop altogether, you don't seem to need it:
if keys[pygame.K_SPACE]:
pygame.mixer.music.load('ht.mp3')
pygame.mixer.music.play(loops=-1, start=0)
Hope this helps!
You don't receive events because of pygame doesn't started. If you remove your while True loop then pygame will start and begin to receive events

pygame freezes when I try to exit it after running it from IDLE!

I'm running it through the livewires wrapper which is just training wheels for pygame and other python modules in general; but everytime I run it, it'll execute and when I try to exit, it will not respond and then crash.
Any input on how I could go about fixing this would be great. There isn't any input in my textbook and all google seems to yield are results to this problem using pygame itself.
Apparently pygame and Tkinter seem to conflict?
Thanks in advance!
Addendum - This is the code I was trying to run:
from livewires import games
screen_w = 640
screen_h = 480
my_screen = games.Screen (wid, heit)
my_screen.mainloop()
Similar question: Pygame screen freezes when I close it
There isn't any input in my textbook
and all google seems to yield are
results to this problem using pygame
itself.
Those results probably address the same problem you're having. This is the relevant part of the games.py file from livewires, and nowhere does it call pygame.quit():
def handle_events (self):
"""
If you override this method in a subclass of the Screen
class, you can specify how to handle different kinds of
events. However you must handle the quit condition!
"""
events = pygame.event.get ()
for event in events:
if event.type == QUIT:
self.quit ()
elif event.type == KEYDOWN:
self.keypress (event.key)
elif event.type == MOUSEBUTTONUP:
self.mouse_up (event.pos, event.button-1)
elif event.type == MOUSEBUTTONDOWN:
self.mouse_down (event.pos, event.button-1)
def quit (self):
"""
Calling this method will stop the main loop from running and
make the graphics window disappear.
"""
self._exit = 1
def mainloop (self, fps = 50):
"""
Run the pygame main loop. This will animate the objects on the
screen and call their tick methods every tick.
fps -- target frame rate
"""
self._exit = 0
while not self._exit:
self._wait_frame (fps)
for object in self._objects:
if not object._static:
object._erase ()
object._dirty = 1
# Take a copy of the _objects list as it may get changed in place.
for object in self._objects [:]:
if object._tickable: object._tick ()
self.tick ()
if Screen.got_statics:
for object in self._objects:
if not object._static:
for o in object.overlapping_objects ():
if o._static and not o._dirty:
o._erase ()
o._dirty = 1
for object in self._objects:
if object._dirty:
object._draw ()
object._dirty = 0
self._update_display()
self.handle_events()
# Throw away any pending events.
pygame.event.get()
The QUIT event just sets a flag which drops you out of the while loop in the mainloop function. I'm guessing that if you find this file in your Python directory and stick a pygame.quit() after the last line in mainloop, it will solve your problem.
I agree. you need to put the whole program (the part to be executed, not the definitions and such) into a while loop.The problem is that pygame is not told to close when exited in IDLE, but outside of IDLE the closure of the program overrides the need to close pygame.
here is the loop:
done = False
while done==False:
# ALL EVENT PROCESSING SHOULD GO BELOW THIS COMMENT
for event in pygame.event.get(): # User did something
if event.type == pygame.QUIT: # If user clicked close
done=True # Flag that we are done so we exit this loop
#Main program here
pygame.quit()

Categories

Resources