This question already has answers here:
Why doesn't PyGame draw in the window before the delay or sleep?
(1 answer)
How to wait some time in pygame?
(3 answers)
Closed 2 years ago.
I was trying to use pygame to create a script that upon clicking run. The window changes the colours of the screen to blue, grey, red with one second delays between them, and then exit out of that loop and then run the game as per normal being the print("cycle done") code. Unfortunately what happens is that the window opens, hangs for around 3 seconds and then shows a red screen, rather than going through each of the colours.
import pygame as pg
running = True
calibration = False
pg.init()
screen = pg.display.set_mode((600, 400))
screen_rect = screen.get_rect()
clock = pg.time.Clock()
timer = 0
white = (255, 255, 255)
black = (0, 0, 0)
red = (255, 0, 0)
green = (0, 255, 0)
blue = (0, 0, 255)
while running:
for event in pg.event.get():
if event.type == pg.QUIT:
running = False
if not calibration:
pg.time.wait(1000)
screen.fill(blue)
pg.display.flip()
pg.time.wait(1000)
screen.fill(green)
pg.display.flip()
pg.time.wait(1000)
screen.fill(red)
pg.display.flip()
calibration = True
print(calibration)
print("cycle done")
clock.tick(60)
If you just wait for some time, you can use pygame.time.wait or pygame.time.delay. However, if you want to display a message and then wait some time, you need to update the display beforehand. The display is updated only if either pygame.display.update() or pygame.display.flip()
is called. See pygame.display.flip():
This will update the contents of the entire display.
Further you've to handles the events with pygame.event.pump(), before the update of the display becomes visible in the window. See pygame.event.pump():
For each frame of your game, you will need to make some sort of call to the event queue. This ensures your program can internally interact with the rest of the operating system.
This all means that you have to call pygame.display.flip() and pygame.event.pump() before pygame.time.wait():
while running:
for event in pg.event.get():
if event.type == pg.QUIT:
running = False
if not calibration:
pygame.event.pump()
pg.time.wait(1000)
screen.fill(blue)
pg.display.flip()
pygame.event.pump()
pg.time.wait(1000)
screen.fill(green)
pg.display.flip()
pygame.event.pump()
pg.time.wait(1000)
screen.fill(red)
pg.display.flip()
pygame.event.pump()
pg.time.wait(1000)
calibration = True
print(calibration)
print("cycle done")
clock.tick(60)
Related
The screen pops up with the green rectangle but I can't move it.
I don't understand why it won't work. any help would be highly appreciated!
import pygame
pygame.init()
width=1800
height=900
red=(255,0,0)
green=(0,255,0)
blue=(0,0,255)
white=(0,0,0)
black=(255,255,255)
x=800
y=150
running = True
def main():
global running, screen, x, y
screen = pygame.display.set_mode((width,height))
pygame.draw.rect(screen, green,(x,y,100,300))
pygame.display.update()
while running:
ev = pygame.event.get()
for event in ev:
if event.type==pygame.KEYDOWN:
if event.type==pygame.K_RIGHT:
x+=20
pygame.display.update()
if event.type==pygame.QUIT:
pygame.quit()
exit()
pygame.display.update()
main()
You have to draw the object in the application not just before the application loop. See My program will run, but the K_RIGHT command will not work:
import pygame
pygame.init()
width, height = 1800, 900
x, y = 800, 150
def main():
global running, screen, x, y
screen = pygame.display.set_mode((width,height))
clock = pygame.time.Clock()
running = True
while running:
clock.tick(100)
ev = pygame.event.get()
for event in ev:
if event.type==pygame.QUIT:
running = False
if event.type==pygame.KEYDOWN:
if event.type==pygame.K_RIGHT:
x+=20
screen.fill("black")
pygame.draw.rect(screen, "green", (x,y,100,300))
pygame.display.update()
pygame.quit()
exit()
main()
The typical PyGame application loop has to:
handle the events by calling either pygame.event.pump() or pygame.event.get().
update the game states and positions of objects dependent on the input events and time (respectively frames)
clear the entire display or draw the background
draw the entire scene (blit all the objects)
update the display by calling either pygame.display.update() or pygame.display.flip()
limit frames per second to limit CPU usage with pygame.time.Clock.tick
This question already has answers here:
Pygame window not responding after a few seconds
(3 answers)
Closed 12 months ago.
I have the following code to demonstrate my problem:
import pygame
import random
import time
def randPoint(w,h):
p = int(random.random()*w),int(random.random()*h)
return p
width=1000
height=1000
screenColor=(0,0,0)
lineColor=(255,255,255)
pygame.init()
screen=pygame.display.set_mode((width,height))
count = 0
while True:
screen.fill(screenColor)
start = randPoint(width,height)
end = randPoint(width,height)
pygame.draw.line(screen, (255, 255, 255), start, end)
pygame.display.flip()
print(count)
count += 1
time.sleep(0.05)
After about 100 frames the pygame window freezes although the console continues to print new frame counts. What am I missing here?
You'll need to call the pygame.event.get() method within the while loop:
while True:
pygame.event.get()
screen.fill(screenColor)
start = randPoint(width,height)
end = randPoint(width,height)
pygame.draw.line(screen, (255, 255, 255), start, end)
pygame.display.flip()
print(count)
count += 1
time.sleep(0.05)
The above stops the program from freezing, but if you want the X button to work on the window, allowing it to close upon command, simply add this for loop:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
You have to handle the events in the application loop. See pygame.event.get() respectively pygame.event.pump():
For each frame of your game, you will need to make some sort of call to the event queue. This ensures your program can internally interact with the rest of the operating system.
If you don't handle the events, the application stops responding.
clock = pygame.time.Clock()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.fill(screenColor)
start = randPoint(width,height)
end = randPoint(width,height)
pygame.draw.line(screen, (255, 255, 255), start, end)
pygame.display.flip()
print(count)
count += 1
clock.tick(20)
The typical PyGame application loop has to:
limit the frames per second to limit CPU usage with pygame.time.Clock.tick
handle the events by calling either pygame.event.pump() or pygame.event.get().
update the game states and positions of objects dependent on the input events and time (respectively frames)
clear the entire display or draw the background
draw the entire scene (blit all the objects)
update the display by calling either pygame.display.update() or pygame.display.flip()
I wanted to do something after a period of time. On stack overflow I found a question that helps solve that, (Link) but when I run the program the code works, however it goes away after a millisecond. Whereas I want it to stay there after the amount of time I want it to wait. In this case for a test run I am blitting some text onto the screen. Here is the code:
import pygame
# Importing the modules module.
pygame.init()
# Initializes Pygame
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
screen = pygame.display.set_mode((800, 600))
# Sets the screen to pygame looks and not normal python looks.
pygame.display.set_caption("Test Run")
# Changes the title
# Heading
headingfont = pygame.font.Font('Bouncy-PERSONAL_USE_ONLY.otf', 45)
headingX = 230
headingY = 10
class Other():
def show_heading():
Heading = headingfont.render("Health Run!", True, (255, 255, 255))
screen.blit(Heading, (headingX, headingY))
pygame.time.set_timer(pygame.USEREVENT, 100)
running = True
while running:
screen.fill((0,0,0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.USEREVENT:
Other.show_heading()
#Update Display
pygame.display.update()
If you want to draw the text permanently, you need to draw it in the application loop. Set a Boolean variable "draw_text" when the timer event occurs. Draw the text depending on draw_text in the application loop:
draw_text = False
running = True
while running:
screen.fill((0,0,0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.USEREVENT:
draw_text = True
if draw_text:
Other.show_heading()
#Update Display
pygame.display.update()
For more information about timers and timer events, see Spawning multiple instances of the same object concurrently in python, How can I show explosion image when collision happens? or Adding a particle effect to my clicker game and many more.
I an having an error with MOUSEBUTTONDOWN giving an error when used.
Here is the error:
if event.type == MOUSEBUTTONDOWN:
NameError: name 'MOUSEBUTTONDOWN' is not defined
Here is the code that is giving the error:
import pygame
import random
import sys
# Define some colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
pygame.init()
# Set the width and height of the screen [width, height]
size = (700, 500)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("game")
# Loop until the user clicks the close button.
done = False
# Used to manage how fast the screen updates
clock = pygame.time.Clock()
# -------- Main Program Loop -----------
while not done:
# --- Main event loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# --- Game logic should go here
# --- Screen-clearing code goes here
# Here, we clear the screen to white. Don't put other drawing commands
# above this, or they will be erased with this command.
# If you want a background image, replace this clear with blit'ing the
# background image.
screen.fill(WHITE)
# --- Drawing code should go here
monospace = pygame.font.SysFont("Berlin Sans FB", 169)
label = monospace.render("test", 1, (0, 0, 0))
screen.blit(label, (100, 100))
button_rect = pygame.Rect(0, 0, 50, 50) # start button rectangle
abort = False
start = False
while not abort and not start:
for event in pygame.event.get():
if event.type == pygame.QUIT:
abort = True
if event.type == MOUSEBUTTONDOWN:
if button_rect.collidepoint(event.pos):
start = True
# draw title screen
# [...]
done = abort
while not done:
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# --- Go ahead and update the screen with what we've drawn.
pygame.display.flip()
# --- Limit to 60 frames per second
clock.tick(60)
# Close the window and quit.
pygame.quit()
All the other sources on Stack Overflow about this topic that I can find all talk about errors where MOUSEBUTTONDOWN already works.
Also note that I am using Pycharm.
Either pygame.MOUSEBUTTONDOWN instead of MOUSEBUTTONDOWN or from pygame.locals import *
You need only one application loop:
import pygame
from pygame.locals import *
import random
import sys
# Define some colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
pygame.init()
# Set the width and height of the screen [width, height]
size = (700, 500)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("game")
clock = pygame.time.Clock()
monospace = pygame.font.SysFont("Berlin Sans FB", 169)
label = monospace.render("test", 1, (0, 0, 0))
button_rect = pygame.Rect(0, 0, 50, 50) # start button rectangle
abort = False
start = False
while not abort:
for event in pygame.event.get():
if event.type == pygame.QUIT:
abort = True
if event.type == MOUSEBUTTONDOWN:
if not start and button_rect.collidepoint(event.pos):
start = True
screen.fill(WHITE)
if not start:
# draw title screen
pygame.draw.rect(screen, "red", button_rect)
else:
# draw game
# [...]
screen.blit(label, (100, 100))
pygame.display.flip()
clock.tick(60)
pygame.quit()
The typical PyGame application loop has to:
limit the frames per second to limit CPU usage with pygame.time.Clock.tick
handle the events by calling either pygame.event.pump() or pygame.event.get().
update the game states and positions of objects dependent on the input events and time (respectively frames)
clear the entire display or draw the background
draw the entire scene (blit all the objects)
update the display by calling either pygame.display.update() or pygame.display.flip()
Solution found:
I did not have the needed libraries imported:
For MOUSEBUTTONDOWN to work you need to use:
from pygame.locals import *
Credit to #Rabbid76 for answering in comments.
Hi I'm having some trouble realizing my ideas. I first wanted to draw rectangles with two mouse clicks, but it didn't work properly so i reduced it to this: to draw fixed-size rectangles with one mouse click.
However it still doesn't work/...
import pygame
windowSize = (500,500)
white = (255,255,255)
black = (0,0,0)
pygame.init()
screen = pygame.display.set_mode(windowSize)
running = 1
while running:
screen.fill(white)
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
running = 0
THE PROBLEM IS HERE SOMEWHERRE
elif event.type == pygame.MOUSEBUTTONDOWN:
rect = pygame.Rect(event.dict["pos"],(30,50))
pygame.draw.rect(screen,black,rect,1)
pygame.display.flip()
I know there might be a lot of conceptual errors with my code... please help!
You are filling white the entire screen every tick. So after you actually draw the screen become blank again on the next tick. Just move screen.fill(white) out of main cycle:
import pygame
windowSize = (500,500)
white = (255,255,255)
black = (0,0,0)
pygame.init()
screen = pygame.display.set_mode(windowSize)
running = 1
screen.fill(white)
while running:
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
elif event.type == pygame.MOUSEBUTTONDOWN:
rect = pygame.Rect(event.dict["pos"],(30,50))
pygame.draw.rect(screen,black,rect,1)
pygame.display.flip()