How do I stop continuous loop of KEYDOWN? - python

I am new to pygame. Whenever I press the key "Delete". It prints "key" continuously. I only want it to print it only one time. How can I do this ?
import pygame
import sys
sprite = "sprite_1.jpg"
position = (20,0)
canvas = pygame.display.set_mode((952, 592))
color = (255,255,255)
exit = False
back = pygame.image.load("th.jpg").convert_alpha()
back = pygame.transform.scale(back, (952,592))
Sprite = pygame.image.load(sprite)
Sprite.set_colorkey((255,255,255))
Sprite = pygame.transform.scale(Sprite, (35,35))
pygame.display.set_caption("Game")
while not exit:
canvas.fill(color)
canvas.blit(back, dest = (0,0))
canvas.blit(Sprite, dest=position)
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit = True
if (event.type == pygame.KEYDOWN):
if (event.key == pygame.K_DELETE):
print("hi")
pygame.display.update()
Please tell the solution. Thanks in advance

It is a matter of Indentation. The event has to be handled in the event loop instead of the applicaition loop:
while not exit:
canvas.fill(color)
canvas.blit(back, dest = (0,0))
canvas.blit(Sprite, dest=position)
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit = True
# INDENTATION
#-->|
if (event.type == pygame.KEYDOWN):
if (event.key == pygame.K_DELETE):
print("hi")
pygame.display.update()

count=0
while not exit:
enter code herecanvas.fill(color)
canvas.blit(back, dest = (0,0))
canvas.blit(Sprite, dest=position)
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit = True
if (event.type == pygame.KEYDOWN):
if count<=0:
if (event.key == pygame.K_DELETE):
print("hi")
else:
continue
pygame.display.update()

Related

how do i make a window quit in pygame?

I want to close the game after was pressed the esc button. how can I do? And where should I place it?
I also found some problems that I can't solve, so if you solve them for me I would be happy
This is the code:
#Import Libraries
import pygame
import random
#PyGame Initialization
pygame.init()
#Images Variables
background = pygame.image.load('images/sfondo.png')
bird = pygame.image.load('images/uccello.png')
base = pygame.image.load('images/base.png')
gameover = pygame.image.load('images/gameover.png')
tube1 = pygame.image.load('images/tubo.png')
tube2 = pygame.transform.flip(tube1, False, True)
#Display Create
display = pygame.display.set_mode((288,512))
FPS = 60
#Define Functions
def draw_object():
display.blit(background, (0,0))
display.blit(bird, (birdx, birdy))
def display_update():
pygame.display.update()
pygame.time.Clock().tick(FPS)
def animations():
global birdx, birdy, bird_vely
birdx, birdy = 60, 150
bird_vely = 0
#Move Control
animations()
while True:
bird_vely += 1
birdy += bird_vely
for event in pygame.event.get():
if ( event.type == pygame.KEYDOWN
and event.key == pygame.K_UP):
bird_vely = -10
if event.type == pygame.QUIT:
pygame.quit()
draw_object()
display_update()
Well you do so by implementing below code snippet in your code:
running = True
while running:
# other code
event = pygame.event.wait ()
if event.type == pygame.QUIT:
running = False # Be interpreter friendly
pygame.quit()
Make sure that you call pygame.quit() before you exit your main function
You can also reference this thread
Pygame escape key to exit
You must terminate the application loop when the QUIT event occurs. You have implmented the QUIT event, but you don't terminate the loop. Add a variabel run = True and set run = False when the event occurs.
To terminate the game when ESC is pressed you have to implement the KEYDOWN event. Set run = False when the KEDOWN event occurs and event.key == pgame.K_ESC:
run = True
while run:
bird_vely += 1
birdy += bird_vely
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
elif event.type == pygame.KEYDOWN:
if event.key == pgame.K_ESC:
run = False
elif event.key == pygame.K_UP:
bird_vely = -10
draw_object()
display_update()
pygame.quit()
exit()

Pygame error: pygame.error: display Surface quit

So I created a Python game Tetris based on Youtube tutorial:
https://www.youtube.com/watch?v=zfvxp7PgQ6c&t=2075s
But the pygame.error: display Surface quit occurs.
I have tried to add "break", "sys.exit()", "QUIT" after the pygame.quit but does not work.
Does anyone know how to solve it? Here is the code: (You can skip to the def main_menu)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run == False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
current_piece.x -= 1
if not (valid_space(current_piece, grid)):
current_piece.x += 1
if event.key == pygame.K_RIGHT:
current_piece.x += 1
if not (valid_space(current_piece, grid)):
current_piece.x -= 1
if event.key == pygame.K_DOWN:
current_piece.y += 1
if not (valid_space(current_piece, grid)):
current_piece.y -= 1
if event.key == pygame.K_UP:
current_piece.rotation += current_piece.rotation + 1 % len(current_piece.shape)
if not (valid_space(current_piece, grid)):
current_piece.rotation -= 1
shape_pos = convert_shape_format(current_piece)
for i in range(len(shape_pos)):
x, y = shape_pos[i]
if y > -1:
grid[y][x] = current_piece.color
if change_piece:
for pos in shape_pos:
p = (pos[0], pos[1])
locked_positions[p] = current_piece.color
current_piece = next_piece
next_piece = get_shape()
change_piece = False
score += clear_rows(grid, locked_positions) * 10
draw_window(win, grid, score, last_score)
draw_next_shape(next_piece, win)
pygame.display.update()
if check_lost(locked_positions):
draw_text_middle(win, "You Lost!", 80, (255,255,255))
pygame.display.update()
pygame.time.delay(1500)
run = False
update_score(score)
def main_menu(win):
run = True
while run:
win.fill((0,0,0))
draw_text_middle(win, 'Press any key to play', 60, (255,255,255))
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.display.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
main(win)
pygame.display.QUIT()
win = pygame.display.set_mode((s_width, s_height))
pygame.display.set_caption('Tetris')
main_menu(win)
Updated code:
def main_menu(win):
run = True
while run:
win.fill((0,0,0))
draw_text_middle(win, 'Press any key to play', 60, (255,255,255))
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
main(win)
pygame.quit()
win = pygame.display.set_mode((s_width, s_height))
pygame.display.set_caption('Tetris')
main_menu(win)
In your main_menu loop you are telling it to loop while local boolean run == True. This is okay, but you should as people mentioned in the comments do a pygame.quit() and optionally quit() (closes the window) instead of the pygame.display.quit() and sys.exit() that you have right now.
The second problem occurs if you start the game by going into the main loop. I assume that the main loop runs your events function shown at the top?
Depending on how you have written the code, the boolean run in the event function is
local. This means that it will not change the value of the run you are using in your
main loop (nor change it in the main_menu loop). I would suggest to transfer into OOP and create a self.run boolean instead,
or else you need to make the boolean run global.
And you should in the event function write this instead of what you have now at the
top:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.quit()
quit()
Hope this helps!

Why doesn't this loop run properly?

while g.running:
for event in pygame.event.get():
if event == pygame.QUIT:
g.running = False
g.run(Player_1)
quit()
when I run this loop it completely skips the for loop or just does it once and is too fast for me to be able to run and it just goes on to run. How do I make the loop work fine?
https://github.com/maartenww/100daysOfCode_projectOne << for the full code.
Also, what g.run basically does is just update the game. So it draws and or moves all the sprites, draws the text unto the screen and does some calculations
class Game:
def __init__(self):
self.running = True
def run(self, player_1):
self.border_col(player_1)
self.load_text(player_1)
self.update_game(player_1)
def update_game(self, player_1):
clock.tick(FPS)
gameDisplay.fill(black)
gameDisplay.blit(self.xcolon, (0, 0))
gameDisplay.blit(self.actual_x, (25, 0))
gameDisplay.blit(self.ycolon, (0, 30))
gameDisplay.blit(self.actual_y, (25, 30))
gameDisplay.blit(self.acolon, (0, 60))
gameDisplay.blit(self.actual_a, (25, 60))
gameDisplay.blit(self.vcolon, (0, 90))
gameDisplay.blit(self.actual_v, (25, 90))
all_sprites.draw(gameDisplay)
Player.move_player(player_1)
Player.update_player(player_1)
pygame.display.update()
I looked into your repo, and the revelant code is this, in player.py:
def move_player(self):
for event in pygame.event.get():
# Player movement
if (event.type == pygame.KEYDOWN):
if (event.key == pygame.K_d):
self.player_acc = PLAYER_ACC
if (event.key == pygame.K_a):
self.player_acc = -PLAYER_ACC
if (event.type == pygame.KEYUP):
if (event.key == pygame.K_d):
self.player_acc = 0
if (event.key == pygame.K_a):
self.player_acc = 0
Think about what happens in your main loop:
while g.running:
for event in pygame.event.get():
if (event.type == pygame.QUIT):
g.running = False
g.run(Player_1)
You get all events from the event queue, clearing it, and check for QUIT.
Then you call g.run, which will call self.update_game, which will call Player.move_player, which will again get all events from the event queue and clear it.
So when the QUIT event is in the event queue at the moment pygame.event.get() is called inside Player.move_player, it is practically lost, since you don't handle it in this for loop. When pygame.event.get() is then called again in main, the QUIT event is no longer in the queue (because calling event.get clears the queue).
Basically, you should call 'event.get' only once per main loop iteration (the same is true for pygame.display.flip/pygame.display.update).
Maybe change the loop in main to something like this:
while g.running:
for event in pygame.event.get():
g.handle(event, Player_1)
g.run(Player_1)
add this to Game:
def handle(self, event, player_1):
if event.type == pygame.QUIT:
self.running = False
else:
player_1.handle(event)
and this to Player:
def handle(self, event):
# Player movement
if (event.type == pygame.KEYDOWN):
if (event.key == pygame.K_d):
self.player_acc = PLAYER_ACC
if (event.key == pygame.K_a):
self.player_acc = -PLAYER_ACC
if (event.type == pygame.KEYUP):
if (event.key == pygame.K_d):
self.player_acc = 0
if (event.key == pygame.K_a):
self.player_acc = 0
and remove Player.move_player
I expect the loop does run, but you've hit a case of type mismatch not being reported.
for event in pygame.event.get():
if event == pygame.QUIT:
event will be a pygame.event.Event object. The QUIT value you're checking against is a value that might appear in the event.type attribute. Since no event is the integer value QUIT, all events are being ignored. You might want to add an else clause to diagnose which events are received but not handled.

UnboundLocalError: pygame music play and stop not working (on keydown)

I'm trying to play and stop a music in my main page.
It's kind of weird.
From my code,
if the user press "m", suppose, the music should be off.
However, the music didn't off. It continue
UnboundLocalError: local variable 'music_playing' referenced before assignment
Can someone help me with my code?
pickUpSound = pygame.mixer.music.load('test.mp3')
pygame.mixer.music.play(-1)
music_playing = True
def mainMenu():
main = pygame.image.load('menu.jpg')
screen.blit(main,(0,0))
while True:
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == KEYDOWN:
if event.key == ord('m'):
if music_playing:
pygame.mixer.music.stop()
else:
pygame.mixer.music.play(-1)
music_playing = not music_playing
As it is written, event.type should be simultaneously equal to KEYDOWN and pygame.K_KP_ENTERat the same time. The second should be event.key instead of event.type.
if event.key == pygame.K_KP_ENTER:
EDIT
There seems to be something wrong with the "keypad enter" key, I commented the problematic line (maybe try with another key, for example, I used K_a, and was able to start/stop by pressing "a")
import pygame
def mainMenu():
pygame.display.init()
pygame.display.set_mode([128,128])
screen = pygame.display.get_surface()
#
pygame.mixer.init()
pickUpSound = pygame.mixer.music.load('test.mp3')
pygame.mixer.music.play(-1)
music_playing = True
#
main = pygame.image.load('menu.jpg')
screen.blit(main,(0,0))
while True:
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
#if event.key == pygame.K_KP_ENTER:
if music_playing:
pygame.mixer.music.stop()
print "stopping"
else:
pygame.mixer.music.play(-1)
print "playing"
music_playing = not music_playing
mainMenu()
n.b. When running this code, I see the messages "playing" and "stopping" each time I press any key.
With if event.key == pygame.K_a: the music should start/stop by pressing "a".

Pygame doesn't CLOSE

Can someone PLEASE tell me what I'm doing wrong. I can't get my stupid program to close. It has a spinning circle(windows) and it doesn't close upon quit or keypress on the space bar.
def visualize(self):
pygame.init()
main_surface = pygame.display.set_mode((1024, 768))
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
break
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
break
pygame.display.flip()
pygame.quit()
I'm not sure if the inside of my program matters much, but if it does, I'll add it. I would REALLY appreciate your help!
The break will just exit the innermost loop, which is the for loop. You should have a condition variable for your while loop
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
break
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
break
pygame.display.flip()

Categories

Resources