[EDIT] I've posted the solution down there. [/EDIT]
I've found two related questions:
But I want to be specific. How to?
while not done:
for e in event.get():
if e.type == KEYDOWN:
keys = key.get_pressed()
if e.type == QUIT or keys[K_ESCAPE]:
done = True
if keys[K_DOWN]:
print "DOWN"
When I press the down arrow, it prints, but it prints just once. If I want to print it another time, I need to press it again.
If I use the while keyword instead,
while keys[K_DOWN]:
print "DOWN"
I get an infinite loop for some obscure reason.
This logical alternative is also useless:
if ((e.type == KEYDOWN) and keys[K_DOWN]):
print "DOWN"
And there is this other one that somehow cleans the events and you can use while:
while not done:
for e in event.get():
if e.type == KEYDOWN:
keys = key.get_pressed()
if e.type == QUIT or keys[K_ESCAPE]:
done = True
while keys[K_DOWN]:
print "DOWN"
event.get()
keys = key.get_pressed()
But you press the down key for less than one second and it prints thousands of times. (Moving a player would be impossible, and adjusting clock for this does not seem to be the right way to deal with it (And I've tried and I've failed miserably.)).
To press and execute the block thousands of times is useless. What I want, is to press the key and keep going with the action while I don't release it, within the defined game clock speed.
I am using a different approach on holding down a key that I am using in the specific task of moving an object left or right.
I do not care about the computer knowing that a key is actually held down.
When I press a key, a variable that I define for that key (EG: left arrow) is set to True. Until that key is unpressed (with the event pygame.KEYUP) the "movement to left" is performed.
[EDIT]Dominik's solution is the perfect one (Separating event.get() from the keyboard ones). It works perfectly!! Finally, no more problems with pygame's input.[/EDIT]
Flags:
You can get
keydown
event repeatedly if you usepygame.key.set_repeat(# millisecond)
to set the time limitation for each key event. Quote: when the keyboard repeat is enabled, keys that are held down will generate multiple pygame.KEYDOWN events. The delay is the number of milliseconds before the first repeated pygame.KEYDOWN will be sent. After that another pygame.KEYDOWN will be sent every interval milliseconds. If no arguments are passed the key repeat is disabled. When pygame is initialized the key repeat is disabled. please see following link for detail http://www.pygame.org/docs/ref/key.html#pygame.key.set_repeatI am not familiar with Pygame, but, as I see, the program in it should have an event-based architecture. Unless you get the incoming events and process them, nothing happens. That's why your simple loop becomes infinite: it just does not process events.
Then concerning the
get_pressed()
call. What it returns is a list of keys. So, you are trying to just loop until the key is released. That's a problem. According to this,pygame.event.get()
returns immediately even if there are no events in the queue. The call toget()
means: my code still has what to do, but I don't want to block the events, so please process the pending events before I continue. If your code is just waiting for an event, that means it has nothing to do.The function to WAIT (without blocking the inner loop of Pygame) for an event is
pygame.event.wait()
(the logic is: I have nothing to do in my code until something happens). However, if you use it, you will have to get information about keys pressed or released from the event itself, not fromget_pressed()
.Here is an example from the comments to the doc page:
This is basically How I did it, well Go to www.cswonders.com, and it might help you . Go to level 3, then 3.6, and go through the tutorial. I learned it from there. Here is my code.
Don't mix up
event.get()
andkey.get_pressed()
.If you press or release a key, and event is put into the event queue, which you query with
event.get()
. Do this if you're actually interested if a key was pressed down physically or released (these are the actual keyboard events. Note that KEYDOWN get's added multiple time to the queue depending on the key-repeat settings).Also, there's no need to query the state of all keys while handling a
KEYDOWN
event, since you already know which key is pressed down by checkingevent.key
If you're interested in if a key is hold down (and ignoring the key-repeat, which you probably want), then you should simply use
key.get_pressed()
. Using a bunch of flags is just unnecessary and will clutter up your code.So your code could simplified to: