views:

1063

answers:

4

I am developing a simple game in PyGame... A rocket ship flying around and shooting stuff.


Question: Why does pygame stop emitting keyboard events when too may keys are pressed at once?

About the Key Handling: The program has a number of variables like KEYSTATE_FIRE, KEYSTATE_TURNLEFT, etc...

  1. When a KEYDOWN event is handled, it sets the coorsponding KEYSTATE_* variable to True.
  2. When a KEYUP event is handled, it sets the same variable to False.

The problem: If UP-ARROW and LEFT-ARROW are being pressed at the same time, pygame DOES NOT emit a KEYDOWN event when SPACE is pressed. This behavior varies depending on the keys. When pressing letters, it seems that I can hold about 5 of them before pygame stops emitting KEYDOWN events for additional keys.

Verification: In my main loop, I simply printed each event received to verify the above behavior.

The code: For reference, here is the (crude) way of handling key events at this point:

while GAME_RUNNING:
    FRAME_NUMBER += 1
    CLOCK.tick(FRAME_PER_SECOND)

    #----------------------------------------------------------------------
    # Check for events
    for event in pygame.event.get():
        print event

        if event.type == pygame.QUIT:
            raise SystemExit()

        elif event.type == pygame.KEYDOWN and event.dict['key'] == pygame.K_UP:
            KEYSTATE_FORWARD = True
        elif event.type == pygame.KEYUP and event.dict['key'] == pygame.K_UP:
            KEYSTATE_FORWARD = False

        elif event.type == pygame.KEYDOWN and event.dict['key'] == pygame.K_DOWN:
            KEYSTATE_BACKWARD = True
        elif event.type == pygame.KEYUP and event.dict['key'] == pygame.K_DOWN:
            KEYSTATE_BACKWARD = False

        elif event.type == pygame.KEYDOWN and event.dict['key'] == pygame.K_LEFT:
            KEYSTATE_TURNLEFT = True
        elif event.type == pygame.KEYUP and event.dict['key'] == pygame.K_LEFT:
            KEYSTATE_TURNLEFT = False

        elif event.type == pygame.KEYDOWN and event.dict['key'] == pygame.K_RIGHT:
            KEYSTATE_TURNRIGHT = True
        elif event.type == pygame.KEYUP and event.dict['key'] == pygame.K_RIGHT:
            KEYSTATE_TURNRIGHT = False

        elif event.type == pygame.KEYDOWN and event.dict['key'] == pygame.K_SPACE:
            KEYSTATE_FIRE = True
        elif event.type == pygame.KEYUP and event.dict['key'] == pygame.K_SPACE:
            KEYSTATE_FIRE = False

    # remainder of game loop here...

For pressing this sequence:

  • a (down)
  • s (down)
  • d (down)
  • f (down)
  • g (down)
  • h (down)
  • j (down)
  • k (down)
  • a (up)
  • s (up)
  • d (up)
  • f (up)
  • g (up)
  • h (up)
  • j (up)
  • k (up)

Here is the output:

  • <Event(2-KeyDown {'scancode': 30, 'key': 97, 'unicode': u'a', 'mod': 0})>
  • <Event(2-KeyDown {'scancode': 31, 'key': 115, 'unicode': u's', 'mod': 0})>
  • <Event(2-KeyDown {'scancode': 32, 'key': 100, 'unicode': u'd', 'mod': 0})>
  • <Event(2-KeyDown {'scancode': 33, 'key': 102, 'unicode': u'f', 'mod': 0})>
  • <Event(3-KeyUp {'scancode': 30, 'key': 97, 'mod': 0})>
  • <Event(3-KeyUp {'scancode': 31, 'key': 115, 'mod': 0})>
  • <Event(3-KeyUp {'scancode': 32, 'key': 100, 'mod': 0})>
  • <Event(3-KeyUp {'scancode': 33, 'key': 102, 'mod': 0})>
  • <Event(2-KeyDown {'scancode': 36, 'key': 106, 'unicode': u'j', 'mod': 0})>
  • <Event(2-KeyDown {'scancode': 37, 'key': 107, 'unicode': u'k', 'mod': 0})>
  • <Event(3-KeyUp {'scancode': 36, 'key': 106, 'mod': 0})>
  • <Event(3-KeyUp {'scancode': 37, 'key': 107, 'mod': 0})>


Is this a common issue? Is there a workaround? If not, what is the best way to handle multiple-key control issues when using pygame?

Thanks!

+7  A: 

This sounds like a input problem, not a code problem - are you sure the problem isn't the keyboard itself? Most keyboards have limitations on the number of keys that can be pressed at the same time. Often times you can't press more than a few keys that are close together at a time.

To test it out, just start pressing and holding letters on the keyboard and see when new letters stop appearing.

My suggestion is to try mapping SPACE to a different key somewhere else and see what happens.

Daniel Lew
Further evidence to back this assertion (from http://www.pygame.org/docs/ref/key.html#pygame.key.get_pressed): "Depending on your keyboard there may be limitations of how many simultaneous keypresses can be detected by this command. Some combinations will work on one keyboard and not on another."
Adam Bernier
+1  A: 

It may very well depend on the keyboard. My current no-name keyboard only supports two keys pressed at the same time, often a pain in games.

mjard
+2  A: 

Some keyboards cannot send certain keys together. Often this limit is reached with 3 keys.

Matthew Schinckel
+5  A: 

As others have eluded to already, certain (especially cheaper, lower-end) keyboards have a low quality keyboard matrix. With these keyboards, certain key combinations will lead to the behavior you're experiencing. Another common side effect can be "ghost keys," where the an extra key press will appear in the input stream that was not actually pressed.

The only solution (if the problem is related to the keyboard matrix) is to change your key mapping to use keys on different rows/columns of the matrix, or buy a keyboard with a better matrix.

technomalogical