Why is my basic PyGame module so slow? - python

I've planning on writing a code in Pygame and I was just getting started with the basics and found that the executing code was really slow. When I press a key it takes a while for it to print it in the terminal (there doesn't seem to be any pattern to it).
I'm running Python 2.6, I downgraded after coming across this problem. With further testing I've found that the whole system slows down. Has anyone come across this or got a solution so it runs faster or/and prevents the system from slowing down?
OS - Ubuntu
Hardware - Macbook Pro
import pygame
import pygame.locals
pygame.mixer.init()
screen = pygame.display.set_mode((640, 480))
pygame.display.set_caption("bla")
background = pygame.Surface(screen.get_size())
background = background.convert()
background.fill(pygame.Color("green"))
screen.blit(background, (0, 0))
looping = True
while looping:
for event in pygame.event.get():
if event.type == pygame.QUIT:
looping = False
elif event.type == pygame.KEYDOWN:
keyName = pygame.key.name(event.key)
print "key pressed:", keyName
if event.key == pygame.K_SPACE:
print "Loading Music"
pygame.mixer.music.load("born.mp3")
elif event.key == pygame.K_ESCAPE:
looping = False
pygame.display.flip()
If there's any further information I can provide I would be happy to help.

pyGame is based on SDL which is internally based on threads.
When you have threading, print messages are basically a no-no. Because often times because of the scheduler slices (which are large in SDL), the print messages get delayed. Its not that pygame is slow (it is some situations, but, not in this one), its just that the print statement is in a seperate event thread.
Try doing this in pygame, it'll run pretty well.

Related

Why doesn't the sys module run in Alien Invasion? [duplicate]

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()

Pygame. Mysterious error. Event referenced before assignment error

I am trying to make a python space shooter game with pygame.
The error I am getting is: local variable 'event' referenced before assignment.
It is mysterious, because sometimes it appears and breaks my program, and sometimes it doesn't. There is no pattern to the error occurrences, it just happens randomly out of nowhere.
I could run the program 2 times, and it would work fine, but then I run it again, and it gives this error.
The code that I am showing is a very simplified version of the real program, but it still produces the same error.
import pygame
WIDTH = 640
HEIGHT = 660
FPS = 30
WHITE = (255,255,255)
BLACK = (0,0,0)
RED = (255,0,0)
BLUE = (0,0,255)
GREEN = (0,255,0)
pygame.init()
pygame.mixer.init()
gamedisplay = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Game!")
clock = pygame.time.Clock()
all_sprites = pygame.sprite.Group()
def quit_game():
pygame.quit()
def message_to_screen(msg, colour, x, y):#This function is used to display messages to the game display.
font = pygame.font.SysFont(None, 25)
text = font.render(msg, True, colour)
gamedisplay.blit(text, (x,y))
def start_screen():
global intro_running
intro_running = True
while intro_running:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
quit_game()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
quit_game()
if event.key == pygame.K_a:
main_game_loop()
gamedisplay.fill(WHITE)
message_to_screen("start screen: press \"a\" to start", RED, 200, 200)
pygame.display.update()#Updating the display.
def main_game_loop():
intro_running = False#I make intro_running equal False here so that when this subprogram starts, the start_screen subprogram will end
running = True
while running:
clock.tick(FPS)
pygame.mouse.set_visible(0)#Makes the mouse invisible.
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
quit_game()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
quit_game()
gamedisplay.fill(GREEN)
message_to_screen("Main game will be here", RED, 200, 200)
all_sprites.draw(gamedisplay)
all_sprites.update(event)#The event parameter needs to be passed, because some sprites in the group need it to check for events.
pygame.display.update()
start_screen()
The full error is:
Traceback (most recent call last):
File "C:/Users/Home/Documents/Python/pygame/test game/re-creation.py", line 106, in <module>
start_screen()
File "C:/Users/Home/Documents/Python/pygame/test game/re-creation.py", line 64, in <module>
main_game_loop()
File "C:/Users/Home/Documents/Python/pygame/test game/re-creation.py", line 98, in <module>
all_sprites.update(event)#All sprites will be updated, each frame.
builtins.UnboundLocalError: local variable 'event' referenced before assignment
All help will be greatly appreciated.
Thank you.
Your sprites probably doesn't need the event argument but it's your game...you can easily fix this by placing it inside the event loop, since your error was caused because event was never defined during the first iteration of the while loop since there wasn't any event therefore the variable event was never generated.
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
quit_game()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
quit_game()
all_sprites.update(event) # this will guarantee that there's an event
But you can also consider doing this to make sure the sprite will always get updated:
class mysprite(pygame.sprite.Sprite): # example sprite class
def __init__(self, event = None): # allow the event to have a default None argument
if event is None:
# do stuff without the event
return
# do stuff with the event
# the event loop snippet
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
quit_game()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
quit_game()
all_sprites.update(event) # this will guarantee that there's an event
all_sprites.update() # without the event outside of the event loop in the while loop, where the all_sprites.update(event) used to be in your example, so the sprites will always get updated
In addition to what was provided in the other answer (you have to apply what is suggested there) there are also other causes of trouble with Pygame:
Pygame mysterious errors could have something to do with what else is going on the computer. I run your script thousand times without any error, BUT ... I witnessed while using a screenshot utility to capture the Pygame window a freezing display to a degree that I had to reboot the computer (but only if special timing of closing the Pygame window and doing the screenshot came together). From this experience I suggest in case the advice given in the other answer doesn't prevent your game from crash for what reason ever:
CHECK which of the applications running in background or foreground may have interfere with Pygame.
It could maybe be easy to detect as there are times the error occurs and times at which it doesn't, but if in addition a special timing of events of the application which interfere with Pygame is necessary for the error to occur it could be very hard to find.
There is no guarantee that this will solve your problem, but maybe it can.
If you want to witness yourself that Pygame handling of events and refreshing the display is not well designed just run a very simple Pygame application doing nothing else as showing an empty window with FPS of one frame per second (FPSclock = pygame.time.Clock() -> FPSclock.tick(1)). If on your box happens the same as on mine you will see the CPU being extremely busy with Pygame. Pygame is just a TOY - don't expect from it too much ...
Maybe you can find out how to modify your code to avoid that the special error occurs, BUT this is with high probability a kind of lottery game. I suppose there is no way to make Pygame run 100% safe from errors and problems under any circumstances. If you want that, switch to another known as stable and mature gaming engine.
It's life - if you gain something on one side you loose some on the other side. There is sure a price to pay for the ease of programming games with Pygame - maybe you can arrange yourself with accepting that it is not a problem if occasionally a mystic error comes out of nowhere?

Undefined variable from import PyGame_SDL2 in PyDev?

I'm creating an android game in PyDev using pygame_sdl2 and RAPT, but I keep getting these errors on specific lines of code:
# V here V
elif ev.type == pygame.KEYDOWN and ev.key == pygame.K_AC_BACK:
which gives me:
Undefined variable from import: K_AC_BACK
I'm wondering if this is a pygame error or a PyDev error; some people seem to be having similar problems with PyDev itself (like so) but I tried those and nothing happens.
Could anyone please give me some direction on how to fix this?
With the latest version of Pygame at the time of writing, the problem is not reproducible. The following minimal example runs without any problems:
import pygame
screen = pygame.display.set_mode()
clock = pygame.time.Clock()
run = True
while run:
for ev in pygame.event.get():
if ev.type == pygame.QUIT:
run = False
elif ev.type == pygame.KEYDOWN and ev.key == pygame.K_AC_BACK:
print('K_AC_BACK')
pygame.display.update()
clock.tick(60)
pygame.quit()

Why is this tiny pygame program freezing and doing nothing?

This program infinite loops. Does nothing. Won't take input or print anything. Ideas?
import pygame
pygame.init()
running = 1
while(running):
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
print "hi"
running = 0
The problem with your script is solely that there's no window that could capture the events.
You have to create and initialize a window with pygame.display.set_mode first.
import pygame
pygame.init()
# create a window that will capture the events
pygame.display.set_mode((200, 200))
running = 1
while(running):
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
print "hi"
running = 0
Try the following:
import pygame, sys
pygame.init()
pygame.mixer.init(22050, -16, 2, 3072)
pygame.mixer.music.load("Kundara_Lake-of-Dust-320.mp3")
pygame.mixer.music.play(1, 0.0)
running = 1
while(running):
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.mixer.music.stop()
pygame.quit()
running = 0
From http://www.pygame.org/docs/ref/pygame.html
pygame.quit
Uninitialize all pygame modules that have previously been initialized. When the Python interpreter shuts down, this method is called regardless, so your program should not need it, except when it wants to terminate its pygame resources and continue. It is safe to call this function more than once: repeated calls have no effect.
Note, that pygame.quit will not exit your program. Consider letting your program end in the same way a normal python program will end.
You are looping infinitely calling pygame.quit() due to while(1).
You need to update the screen. Try it with
screen = pygame.display.set_mode((640,360),0,32)
and in the loop, write
pygame.dispay.flip()
to close the window completely, you can use
sys.exit()
just be sure to include sys in your imports
pygame does not recognize the term 'input' or 'print'. It would be a lot simpler if it did!! Instead, to get text onto the screen, you must use 'drawText('message',font,surface,(xpos,ypos) putting your own text in 'message', your own surface name in 'surface' and the x and y co-ordinates in 'xpos' and 'ypos'.

Playing music with Pygame unreliable

I'm trying to write a simple program to play music files with Pygame. My script is below.
import pygame
import sys
import time
FRAMERATE = 30
if len(sys.argv) < 2:
sys.exit(2)
filename = sys.argv[1]
clock = pygame.time.Clock()
pygame.init()
pygame.mixer.init(frequency=44100)
pygame.mixer.music.load(filename)
print "%s loaded!" % filename
pygame.mixer.music.play(1)
while pygame.mixer.music.get_busy():
clock.tick(FRAMERATE)
But I'm having some puzzling problems. The "[File name] loaded!" message always prints, but sometimes it never enters the loop and exits immediately. If I check on the status of pygame.mixer.music.get_busy(), it appears to be false immediately after the pygame.mixer.music.play(1) command. This happens erratically; I just tried running the program with no changes to the code, having it work once and encounter this problem once right afterward. Does anyone know what could be causing these seemingly random playback problems?
I imagine this is because the actual music playback is happening on another thread, so it sometimes hasn't finished starting at the point you first call get_busy().
If that's the case, it seems like a bug in either pygame or SDL_mixer (which pygame uses.)
As an alternative way of checking for music completion, you can get pygame to give you an event when the music finishes and check for that. Like this:
pygame.mixer.music.set_endevent(pygame.USEREVENT)
quit = False
while not quit:
clock.tick(FRAMERATE)
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit = True
if event.type == pygame.USEREVENT:
print "Music ended"
quit = True

Categories