How to delay pygame.key.get_pressed()? - python

I haven't been able to find a straightforward answer.
key.set_repeat() works for KEYDOWN events, but not for key.get_pressed():
import sys, pygame
from pygame.locals import *
pygame.init()
Clock = pygame.time.Clock()
pygame.display.set_mode((200, 100))
pygame.key.set_repeat(1, 500)
while True:
if pygame.key.get_pressed()[K_UP]:
print('up!')
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_DOWN:
print('down!')
Clock.tick(30)
Even the slightest tap on UP explodes into at least a few up!s, only down!s are delayed. I want to use key.get_pressed() since it conveniently handles multiple inputs. Do I have to work around it with some sorta tick counter? Alternatively, is there a way to handle multiple KEYDOWN events?

Just don't mess around with key.set_repeat() if you don't have to.
Simply use key.get_pressed() to check for keys that are pressed and where keeping that key pressed down has a meaning to you, e.g. something like move left while K_LEFT is pressed.
Use event.get() / KEYDOWN when you're interessed in a single key press, e.g. something like pressing K_P pauses the game.
If you mess around with key.set_repeat(), e.g. set the delay to low, you won't be able to recognize a single key stroke, since every key stroke will create multiple KEYDOWN events.
To handle multiple KEYDOWN events, just check for the relevant events. Every key stroke will generate a KEYDOWN event, so you can simple check e.g.:
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_DOWN:
print('down!')
elif event.key == K_UP:
print('up!')
That will of course print up!/down! multiple times if the user keeps pressing the keys.
The golden rule is: If you're interessted in the KEYDOWN and the KEYUP event of a single key, better use key.get_pressed() instead.
Even the slightest tap on UP explodes into at least a few up!s, only down!s are delayed
That's because the event system and key.get_pressed() are totally different. If you get pressing K_UP over multiple frames, for each frame 'up!' is printed because the key is pressed down in every frame. key.get_pressed() simple returns which keys are pressed at the moment you call this function. In other words: you can't "delay" it.

Related

How Do I Play An Audio Whenever I Click On a Specific Key On The Keyboard?

So, my idea is to create a program (using the "Keyboard" module) that, while I am pressing on a key ("Enter", in this case), a sound is played (only once), as soon as I stop pressing that key, another sound would be played (only once).
In other words, NASA uses a communications system in which, when a "call" starts, a "beeeep" is played, when the "call" is ended (like an "Over") a "beeeeep" is played again.
This was my first attempt:
import keyboard
import pygame
def BeepOn():
pygame.mixer.init()
pygame.mixer.music.load("Mic On.mp3")
pygame.mixer.music.play(loops=0)
pygame.mixer.music.set_volume(0.50)
def BeepOff():
pygame.mixer.init()
pygame.mixer.music.load("Mic Off.mp3")
pygame.mixer.music.play(loops=0)
pygame.mixer.music.set_volume(0.50)
while True:
if keyboard.on_press_key('Enter'):
BeepOn()
if keyboard.on_release_key('Enter'):
BeepOff()
if keyboard.is_pressed('End'):
exit()
Attention:
I would like you to just have to click on one key instead of two.
I hope I explained it well!
I look forward to an answer (however stupid it may be).
Regards,
Diogo Matos
Here:
import pygame
#Condition for while loop
running = True
def BeepOn():
pygame.mixer.init()
pygame.mixer.music.load("Mic On.mp3")
pygame.mixer.music.play(loops=0)
pygame.mixer.music.set_volume(0.50)
def BeepOff():
pygame.mixer.init()
pygame.mixer.music.load("Mic Off.mp3")
pygame.mixer.music.play(loops=0)
pygame.mixer.music.set_volume(0.50)
while running:
for event in pygame.event.get():
#Tests for quit
if event.type == pygame.QUIT:
running = False
#Tests if enter is pressed
if event.type = pygame.KEYDOWN:
if Event.key == pygame.K_RETURN:
BeepOn()
#Tests if enter is released
if event.type = pygame.KEYUP:
if Event.key == pygame.K_RETURN:
BeepOff()
pygame.quit()
I hope this helps, I'm not familiar with the keyboard module, so I just did it all from pygame. (:
If this helps please let me know...

Pygame reading multiple keydown events when key was not pressed?

I've been trying to develop a "text box" class for pygame as a little personal project, and I've come across an issue that's really stumped me. I'm trying to expand on the pygame text input class found here, wrapping it in a text box class that supports multiple lines and, hopefully, scrolling capabilities.
My problem comes when trying to move the blinker up and down between the lines of text. Basically, hitting the "up" arrow once moves the blinker all the way to the top, and then it stops being responsive to move it down.
Here's the code for how I give the pygame_textbox class the events:
while True:
events = pygame.event.get()
for event in events:
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
test_box.update(events)
test_box_2.update(events)
test_box.draw(screen, (100, 100))
test_box_2.draw(screen, (200, 250))
pygame.display.update()
Here's the code for the text box class (event comes from the above code):
if event.type == pl.KEYDOWN:
if self.is_active:
print("reading in text box: {}".format(event))
if event.key == pl.K_UP and self.cursor_line > 0:
self.cursor_line -= 1
print("cursor going UP to {}".format(self.cursor_line))
if event.key == pl.K_DOWN and self.cursor_line < len(self.text_input)-1:
self.cursor_line += 1
print("cursor going DOWN to {}".format(self.cursor_line))
if event.key == pl.K_RETURN:
self.text_input.insert(self.cursor_line+1, pygame_textinput.TextInput())
self.cursor_line += 1
for line in self.text_input:
print(line.input_string)
Trying to debug it seems to show that the pygame.event.get() queue is taking in way more KEYDOWN events than it's supposed to; one press of the button sends multiple (and sometimes ongoing) events. I'm new to pygame, but I'm pretty sure that's not supposed to happen with KEYDOWN events, right? There's only supposed to be one event triggered every time a key is pressed. What am I doing wrong here? Is this a bug with pygame itself?
Thanks for any help you can provide. I'm fairly new at this and I hope I formatted the question right.
Just take a look at the pygame_textinput module you linked in your question:
# Update key counters:
for key in self.keyrepeat_counters:
self.keyrepeat_counters[key][0] += self.clock.get_time() # Update clock
# Generate new key events if enough time has passed:
if self.keyrepeat_counters[key][0] >= self.keyrepeat_intial_interval_ms:
self.keyrepeat_counters[key][0] = (
self.keyrepeat_intial_interval_ms
- self.keyrepeat_interval_ms
)
event_key, event_unicode = key, self.keyrepeat_counters[key][1]
pygame.event.post(pygame.event.Event(pl.KEYDOWN, key=event_key, unicode=event_unicode))
As you can see, it's the update method of the TextInput that repeats the key events by posting them again to pygame's event queue.

pygame - return key pressed before event.key handler results in immediate processing of event.key block

In my program made with pygame, I have an intro sequence that blits a total of 3 text boxes to the screen timed apart from each other, so one appears, then the next, then the one after that. I have no event polling during this time, as I want the whole sequence to play for it's total of probably around 10 seconds. However, after this sequence plays, I have a 'Continue' text that appears in the bottom right to show the user to press Return to continue to the next slide. This is where I then have my event handler like so:
exited = False
while not exited:
for event in pygame.event.get():
if event.type == pygame.QUIT:
exited = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RETURN:
exited = True
However, if the user hits Return at any time in this sequence, once the control flow hits the event handler, it just exits immediately through the pygame.KEYDOWN branch. How should I go about fixing this?
I have solved this by actually just adding
for event in pygame.event.get():
pass
before my next pygame.event.get() loop. The first one consumes the other events that happened in the sequence, so that the second loop will only handle input given after the sequence plays.

How to determine if a key is pressed in python using pygame

Is there a really simple way of knowing if the key SPACE is currently DOWN. I'm making a basic snake game and I don't know to use pygame and I can't find it anywhere.
I imagine it like something along these lines:
if K_SPACE = DOWN:
turtle.turn(90)
thank you for any help
In your game loop:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
turtle.turn(90)

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'.

Categories