When I want to freeze my pygame window for a few seconds I usually use time.sleep(). However, if I accidentaly press any key on my keyboard meanwhile it detects the key after the time has passed. Is there any way to freeze my pygame window so that the code won’t consider the key pressed?
You have to use pygame.time.wait() rather than time.sleep(). Be aware that the input has to be set in millisecond.
See documentation: time.wait()
Here is an example where the screen will change color every frame. The title bar displays the last key pressed.
If the space bar is pressed, the color change is paused for three seconds. Key presses are ignored, but other events may be handled during this period.
This is accomplished by setting up a custom timer and using a variable to track the paused state.
import pygame
import itertools
CUSTOM_TIMER_EVENT = pygame.USEREVENT + 1
my_colors = ["red", "orange", "yellow", "green", "blue", "purple"]
# create an iterator that will repeat these colours forever
color_cycler = itertools.cycle([pygame.color.Color(c) for c in my_colors])
pygame.init()
pygame.font.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode([320,240])
pygame.display.set_caption("Timer Example")
done = False
paused = False
background_color = next(color_cycler)
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == CUSTOM_TIMER_EVENT:
paused = False
pygame.display.set_caption("")
pygame.time.set_timer(CUSTOM_TIMER_EVENT, 0) # cancel the timer
elif not paused and event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
pygame.time.set_timer(CUSTOM_TIMER_EVENT, 3000)
pygame.display.set_caption("Paused")
paused = True
else:
pygame.display.set_caption(f"Key: {event.key} : {event.unicode}")
if not paused:
background_color = next(color_cycler)
#Graphics
screen.fill(background_color)
#Frame Change
pygame.display.update()
clock.tick(5)
pygame.quit()
EDIT: Change to ignore key-presses during the paused period as the question asked.
Related
I'm making a calculator in pygame but when I click the button, I want the number to stay on the screen but instead of staying on the screen, the number just appears when my mouse is clicked. When I release it, the numbers disappears. Does anyone know a solution for this?
My code:
import pygame
from sys import exit
pygame.init()
screen = pygame.display.set_mode((600,800))
pygame.display.set_caption("Calculator")
clock = pygame.time.Clock()
font1 = pygame.font.Font("c:/Users/oreni/OneDrive/Masaüstü/sprites/minecraft.ttf", 100)
one = 1
one_main = font1.render(str(one), False, "black")
one_main_r = one_main.get_rect(center = (75,100))
one_button = pygame.Surface((142.5,142.5))
one_button.fill("white")
one_button_r = one_button.get_rect(topleft = (0,160))
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
screen.fill("black")
screen.blit(one_button,one_button_r)
if event.type == pygame.MOUSEBUTTONDOWN:
if one_button_r.collidepoint(event.pos):
screen.blit(one_main,one_main_r)
pygame.display.update()
clock.tick(60)
The usual way is to redraw the scene in each frame. You need to draw the text in the application loop. Set a variable that indicates that the image should be drawn when the mouse is clicked, and draw the image according to that variable:
draw_r = False
run = True
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.MOUSEBUTTONDOWN:
if one_button_r.collidepoint(event.pos):
draw_r = True
screen.fill("black")
screen.blit(one_button,one_button_r)
if draw_r:
screen.blit(one_main, one_main_r)
pygame.display.update()
clock.tick(60)
pygame.quit()
exit()
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've been trying to figure how to set up pause and unpause function on my game that allows me to use space to pause and then unpause as well. I've been struggling mostly because I'm so new to coding. I feel like I'm not understanding the true and false or rather the binds.
The code is as follows:
import random
from tkinter import *
def paused(window):
PAUSED = False
while True:
pause(window)
canvas.create_text(canvas.winfo_width() / 2, canvas.winfo_height() / 2, font=('consolas', 70), text="PAUSED", fill="white", tag='paused')
window.keys.bind("<space>", paused)
if not paused:
paused = False
window.update()
I am assuming you are using pygame. In pygame, you can listen to pygame.event and check if the space bar has been clicked.
PAUSED = False
while True:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
PAUSED = not PAUSED # inverts PAUSED
if not PAUSED:
draw() # update
clock.tick(60)
Otherwise, you can use the keyboard module.
I have been trying to get my code collecting which mouse button is pressed and its position yet whenever I run the below code the pygame window freezes and the shell/code keeps outputting the starting position of the mouse. Does anybody know why this happens and more importantly how to fix it?
(For the code below I used this website https://www.pygame.org/docs/ref/mouse.html and other stack overflow answers yet they were not specific enough for my problem.)
clock = pygame.time.Clock()
# Set the height and width of the screen
screen = pygame.display.set_mode([700,400])
pygame.display.set_caption("Operation Crustacean")
while True:
clock.tick(1)
screen.fill(background_colour)
click=pygame.mouse.get_pressed()
mousex,mousey=pygame.mouse.get_pos()
print(click)
print(mousex,mousey)
pygame.display.flip()
You have to call one of the pygame.event functions regularly (for example pygame.event.pump or for event in pygame.event.get():), otherwise pygame.mouse.get_pressed (and some joystick functions) won't work correctly and the pygame window will become unresponsive after a while.
Here's a runnable example:
import pygame
pygame.init()
screen = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()
BG_COLOR = pygame.Color('gray12')
done = False
while not done:
# This event loop empties the event queue each frame.
for event in pygame.event.get():
# Quit by pressing the X button of the window.
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.MOUSEBUTTONDOWN:
# MOUSEBUTTONDOWN events have a pos and a button attribute
# which you can use as well. This will be printed once per
# event / mouse click.
print('In the event loop:', event.pos, event.button)
# Instead of the event loop above you could also call pygame.event.pump
# each frame to prevent the window from freezing. Comment it out to check it.
# pygame.event.pump()
click = pygame.mouse.get_pressed()
mousex, mousey = pygame.mouse.get_pos()
print(click, mousex, mousey)
screen.fill(BG_COLOR)
pygame.display.flip()
clock.tick(60) # Limit the frame rate to 60 FPS.
I want to create a button in my game that can control the background music on and off. The first click will stop the background music, and the second click can bring back the music. Now my button can control the music on and off, but I need to click multiple times to make it work, it seems that the click event is not captured everytime, here is my code:
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
if 20 + 50 > mouse_position[0] > 20 and 20 + 20 > mouse_position[1] > 20:
play_music = not play_music
if play_music:
pygame.mixer.music.unpause()
else:
pygame.mixer.music.pause()
pygame.display.flip()
clock = pygame.time.Clock()
clock.tick(15)
J0hn's answer is correct. Define a boolean variable (e.g. music_paused = False), toggle it when the user clicks on the button and call pygame.mixer.music.pause to stop the music and pygame.mixer.music.unpause to resume the playback of the music stream.
I also recommend doing the collision check in the event loop (for event in pygame.event.get():), because the button should be clicked only once per pygame.MOUSEBUTTONDOWN event. pygame.mouse.get_pressed() will keep clicking the music button as long as the mouse button is down.
import pygame as pg
pg.init()
screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
BG_COLOR = pg.Color('gray12')
BLUE = pg.Color('dodgerblue1')
pg.mixer.music.load('your_music_file.ogg')
pg.mixer.music.play(-1)
button = pg.Rect(100, 150, 90, 30)
music_paused = False
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
elif event.type == pg.MOUSEBUTTONDOWN:
if button.collidepoint(event.pos):
# Toggle the boolean variable.
music_paused = not music_paused
if music_paused:
pg.mixer.music.pause()
else:
pg.mixer.music.unpause()
screen.fill(BG_COLOR)
pg.draw.rect(screen, BLUE, button)
pg.display.flip()
clock.tick(60)
pg.quit()
It looks like you have a pygame.mixer.music.pause() but nothing from resume. I'm not sure how pygame's music mixer works but I'd recommend using a flag that is updated on button click
music = 0 by default, if clicked, set music = 1 then have a check if music == 1: pygame.mixer.music.pause() and if music == 0: pygame.mixer.music.unpause(). Make that check and flag change every time the button is clicked.
ya guys don't need a boolean variable only a small function
def toggleMusic():
if pygame.mixer.music.get_busy():
pygame.mixer.music.pause()
else:
pygame.mixer.music.unpause()
pygame.mixer.music.get_busy() is the boolean you need because this checks if music is playing. if music is playing it will return True and vice versa
I want to make a FPS game in Pygame in windowed mode.
I need to be able to move my camera around for 360 degrees and more without limitation and with the hidden cursor.
I used Pygame's set_visible and set_pos but it doesn't prevent my mouse going out of the window and blocking on the screen borders.
import pygame
pygame.init()
game_display = pygame.display.set_mode((800,600))
pygame.mouse.set_visible(False)
exit = False
while (not exit):
pygame.mouse.set_pos = (400, 300)
mouse_move = (0,0)
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit = True
if event.type == pygame.MOUSEMOTION:
mouse_move = event.rel
if mouse_move != (0,0):
print(mouse_move)
pygame.quit()
You have to call pygame.event.set_grab(True) as well.
Better allow the users to exit with the Esc or another key, because they won't be able to click the x button anymore to close the window.
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
exit = True