3

What is the idiomatic way of saying to pygame to run something as long as a key is being pressed? With pygame.key.get_pressed()[pygame.K_p]==True or pygame.mouse.get_pressed()==(1,0,0) it seems to react only as the key or the button get strocken. Should one use a while loop for example?

I run the code below and i get print in the shell only upon strocking the key/button:

def main():
done = True
while done:
    for i in pygame.event.get():
        if pygame.key.get_pressed()[pygame.K_a] == 1:
            print "Key a is being pressed..."
        elif i.type == KEYDOWN and i.key == pygame.K_q:
            done = 0
    pygame.display.update()
pygame.quit()
main()
  • 2
    don't use `get_pressed()` inside `for ... in pygame.event.get()`. You will repeat function many times - if there was many events - or zero times - if there was no event. – furas Feb 01 '16 at 18:59

2 Answers2

5

Event KEYDOWN means "key changed state from UP to DOWN" - it doesn't means "key is held pressed all time"

enter image description here

When you start pressing key - it generate event KEYDOWN and pygame.event.get() returns not empty list - and for loop can execute if pygame.event.get()

When you hold key pressed - it doesn't generate event KEYDOWN - and pygame.event.get() returns empty list - and for loop doesn't execute if pygame.event.get()

Your code should looks like

running = True
while running:
    # check events 
    for event in pygame.event.get():
        if event.type == KEYDOWN:
            if event.key == pygame.K_q:
               running = False

    # do it outside of `for event` loop
    # it is executed many times 
    if pygame.key.get_pressed()[pygame.K_a]: 
        print "Key is hold pressed..."

    pygame.display.update()

or - when you need to execute something only once

key_A_pressed = False

running = True
while running:
    # check events 
    for event in pygame.event.get():
        if event.type == KEYDOWN:
            if event.key == pygame.K_q:
               running = False

            elif event.key == pygame.K_a:
               key_A_pressed = True

               # it is executed only once
               print "Key A - start pressing"

        if event.type == KEYUP:
            if event.key == pygame.K_a:
               key_A_pressed = False

               # it is executed only once
               print "Key A - stop pressing"

    # do it only once - outside of `for event` loop
    # it is executed many times 
    #if pygame.key.get_pressed()[pygame.K_a]: 
    # or
    if key_A_pressed:
        print "Key A is held pressed..."

    pygame.display.update()
furas
  • 134,197
  • 12
  • 106
  • 148
  • Thanks, so if i understand it correct **holding** a key or button doesn't count as an **event**? So you are not using the `pygame.key.get_pressed` at all? When and where sould it be used if one can stimulate **holding** in such away with `event.type==KEYDOWN` instead? –  Feb 02 '16 at 09:48
2

You should use:

def main():
    done = False
    while not done:
        for i in pygame.event.get():
            if i.type == KEYDOWN and i.key == pygame.K_q:
                done = True

        pressed = pygame.key.get_pressed()     
        if pressed[pygame.K_a]:
            print "Key a is being pressed..."

        pygame.display.update()
    pygame.quit()

if __name__ == '__main__':
    main()

The problem in your code is that you check for pressed keys only while iterating over all recieved events; so in case there's no event, the print "Key a is being pressed..." part can never be executed.

Just put it outside of the event loop.

Also, you don't need to compare against True explicitly; the idiomatic/pythonic way is to just use if pressed[pygame.K_a]:.

sloth
  • 99,095
  • 21
  • 171
  • 219
  • Thanks for your answer. I think there was a misunderstanding for me; it means that `key.get_pressed` should be refreshed over each `while` loop in order to give continuose output? So what would then be the difference between that option and writing `if event.type==KEYDOWN and event.key==pygame.K_a` outside of the while loop? I tried both and it seems they have the same effect. –  Feb 02 '16 at 09:25
  • When you press a key, a `KEYDOWN` event is generated. If you release a key, a `KEYUP` event is generated. Holding a key down does not create new events (except when you enable key repetition, which you should not do). – sloth Feb 02 '16 at 09:55
  • I see. Could you mention an example of where explicitely `key.get_pressed` should be preffered? –  Feb 02 '16 at 10:14
  • Everytime you want to know if a key is being hold down (typically for stuff like: if the LEFT arrow is pressed, keep moving left). – sloth Feb 02 '16 at 11:38