I've been following along with a bouncing ball example just to get my chops warmed up with pygame: every time I test my code I have to kill the game window by causing it to freeze, though in my code (taken directly from the pygame website) I state that the game should exit if the Escape key is pressed or the X button on the screen. I get an error
running == False
NameError: name 'running' is not defined
my code is
while 1:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running == False
if event.type ==pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
running == False
can I define "running?" such that the game doesn't simply freeze when I try to quit.
First off, you should define running to True (running = True) above your while loop. Secondly, you should be checking that value somewhere; easiest is to change while 1 to while running Third, == is checking for equality, = is setting a value. You want to check event.type to be pygame.QUIT or KEYDOWN, so those == are correct, but then you want to set running to False, which is running = False. Doing running == False as a statement is not effective.
Related
I'm working on a project and when I add the clock.tick to my main game loop, my pygame window doesnt close.
def game_loop():
"""The main game loop that runs as the game runs. Returns when the pygame window is closed."""
global running
global timer
while running:
while timer > screen.fixed_fps:
fixed_update()
timer -= screen.fixed_fps
update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
return
screen.clock.tick(screen.fps)
timer += delta_time()
pygame.quit()
return
When I click the X, the screen freezes until I let go, but unless I click the X in a very specific time frame( I usually need to click it 20 times to close) it doesnt work.
This is likely because of the way you are handling the QUIT event in your event loop. The pygame.event.get() function returns all of the events that have occurred since the last time it was called, so if there is a delay in your loop, the QUIT event may not be handled until multiple events have accumulated. To fix this, you should move the QUIT event handling code to the top of your event loop so that it is handled as soon as the event occurs. Also you could try to add pygame.display.update() after the event handling to make sure it is updated.
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
return
while timer > screen.fixed_fps:
fixed_update()
timer -= screen.fixed_fps
update()
screen.clock.tick(screen.fps)
timer += delta_time()
I just spent a fair amount of time finding a 64-bit installation of pygame to use with python 3.3, (here) and now am trying to make a window. However, although the window opens up fine it does not close when it hit the x button. In fact, I have to close IDLE to close the window. I am running a 64 bit version of Win 7. Here is my code:
import pygame
import time
(width, height) = (300, 200)
screen = pygame.display.set_mode((width, height))
pygame.display.flip()
pygame.display.set_caption("Hello World")
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
When I append
time.sleep(5)
pygame.quit()
It still doesn't close. My only guess would be that pygame.quit might go inside one of the loops, but even if that were resolved I would greatly prefer being able to close the window when I want to.
Most pygame tutorials seem to suggest exiting by calling pygame.quit() and then sys.exit(). I have personally run into problems (was on a unix system though) where this still did not close the window properly. The solution was to add pygame.display.quit() specifically before pygame.quit(). That should not be necessary as far as I can tell, and I'm afraid I don't know why that solved the issue but it did.
if you want to make pygame close when window button x is pressed, put the code like this:
from sys import exit
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
We put exit() after pygame.quit(), because pygame.quit() makes the system exit and exit() closes that window.
Not sure but try this Because you code runs fine on my system after I add pygame.quit() at the end
import pygame
import time
(width, height) = (300, 200)
screen = pygame.display.set_mode((width, height))
pygame.display.flip()
pygame.display.set_caption("Hello World")
running = True
try:
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
except SystemExit:
pygame.quit()
Its perhaps because as Idle is made on Tkinter and thus Tkinter and Pygame main loop do not have a mutual understanding.
Your code will run very well on command prompt though.
This was the final code that worked for me on OSX whilst keeping the kernel alive on Jupyter. EDIT - it does still crash the kernel sometimes :-(
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.display.quit()
pygame.quit()
exit()
Also needed to downgrade ipython to get rid of some magic alias warning messages using:
conda install ipython=7.2.0
apparently that issue is due to be fixed in ipython 7.6.0
Suffered the same issues on Python 3.7.4 while running it from in IDE (Spyder 3.3.6). In my case the pygame.quit() would not completely close the program.
Nonetheless, adding quit() or exit() did the trick for me!
Add this at the top:
import sys
Add this where you need to quit:
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
try using the following command:
sys.exit(0)
notice: You will need to import the sys library in order to use it.
The IDE interferes with how pygame runs the code. Try to run it from the commandline or the terminal. The problem should disappear.
To answer the original question: You must call pygame.quit() after breaking the main loop. One elegant solution goes as follows:
def run():
pygame.init()
while True:
# ...
for event in pygame.event.get():
# Handle other events
if event.type == pygame.QUIT:
return pygame.quit()
I'm only starting to grasp this idea of abstracting complex stuff via functions, so I decided to practice it a bit in Pygame.
So, this code right here works just fine, the pygame window is present, and you can close it by pressing X button:
#pygame initialization code and etc.
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
#code for drawing stuff out
But let's say I want to make a function to just handle closing the window just for the sake of it:
#pygame initialization code and etc.
running = True
def handle_quit_event():
for event in pygame.event.get():
if event.type == pygame.QUIT:
return False
else:
return True
while running:
running = handle_quit_event()
#code for drawing stuff out
Now it doesn't work the same way anymore, the pygame window appears for a blink moment, and then program finishes, leaving me with this unease feeling that my idea of abstracting stuff using functions is all wrong.
[EDIT]: So in my code the function checks for only the first event in the list, but it still doesn't explain why the program finishes right after running it, because even if it checks for the first event, it still should return true by running else clause. So what am I missing?
Abstracting functionality into functions is a great idea! Unfortunately your re-write has introduced a bug that might be causing your broken game. Without a stacktrace or error messages, it's hard to say exactly why the game is broken.
Onto the bug:
The function handle_quit_event doesn't iterate through all the events in pygame.event.get(). It returns True or False after checking the first event.
You probably wanted to write it more like:
def handle_quit_event():
for event in pygame.event.get():
if event.type == pygame.QUIT:
return False
return True
A more pythonic approach that uses list-comprehension and any():
def handle_quit_event():
return not any([event.type == pygame.QUIT for event in pygame.event.get()])
Note the flipped logic with not is required because your function is currently returning True if there is not a QUIT event.
Originally after I did some searching here, I found a question with the exact same problem I had:
Pygame window not responding after a few seconds . I reviewed all the answers and tried them, but none of them worked. I tried using for loops to loop through every single event;
run = True
while run:
for event in pygame.event.get():
if event == pygame.QUIT()
run = False
But the window still closed. I also tried:
run = True
while run:
event = pygame.event.get()
if event == pygame.QUIT():
run = False
Which had the same results as the one above.
Can anyone help?
Edit: I use PyCharm and MacOS Catalina.
pygame.QUIT is a constante, but pygame.QUIT() is a call statement. Remove the braces. Anyway, the condition won't work, because you have to compare the type attribute of the event to the event type constant (see pygame.event). Furthermore the : is missing at the end of the if-statement.
if event == pygame.QUIT()
if event.type == pygame.QUIT:
Furthermore the Indentation is not correct:
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
Lets says I just have a normal game loop using pygame.
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.quit()
Where run = False is, should I use run = False and pygame.quit() at the end? Should I just put pygame.quit() where run = False is? Should I use quit() without pygame in front of it at all? Thanks.
I recommend to do it exactly as you do it in the question.
pygame.quit() uninitialize all pygame modules. Any further call to a pygame module (except pygame.init()) will cause an exception. To terminate a pygame application correctly, pygame.quit() has to be the called at the end. If you do pygame.quit() in the main application loop, then the application will crash if you do something after it (e.g. pygame.disaply.update()).