[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] Capturing Multiple Keyboard Inputs



On Mon, Jan 16, 2012 at 20:22, Silver <rockachu2@xxxxxxxxx> wrote:
> On 1/15/2012 8:16 PM, Ian Mallett wrote:
>> On Sun, Jan 15, 2012 at 7:46 PM, Ryan Strunk <ryan.strunk@xxxxxxxxx> wrote:
>>
>>> Hello everyone,
>>> I am testing my understanding of the pygame.key module by creating a
>>> program
>>> that pans the sound of a car engine and raises/lowers its frequency. While
>>> the individual keys do exactly what they're supposed to, I run into a big
>>> problem when I try to do two things at once. For example, if I hold the up
>>> arrow, the frequency of the sound rises with no problem. If I then hold
>>> down
>>> the left arrow while still holding up, however, the frequency stops rising
>>> and the pan begins to adjust itself. How can I make both keys carry out
>>> their assigned task at the same time?
>>> As a side note, aside from exporting the redundant code below into its own
>>> methods, are there any other ways to check for multiple keys without giving
>>> each its own if check?
>>> Ugly code is below:
>>>
>>> import pygame
>>> from sound_lib.stream import FileStream
>>> from sound_lib.output import Output
>>>
>>> def main():
>>> Â Â Â Âclock = pygame.time.Clock()
>>> Â Â Â Âo = Output()
>>> Â Â Â Âsound = FileStream(file="sounds/car.wav")
>>> Â Â Â Âscreen = pygame.display.set_mode((640, 400))
>>> Â Â Â Âsound.looping = True
>>> Â Â Â Âsound.play()
>>> Â Â Â Âpygame.key.set_repeat(50, 50)
>>> Â Â Â Âwhile(True):
>>> Â Â Â Â Â Â Â Âfor event in pygame.event.get():
>>> Â Â Â Â Â Â Â Â Â Â Â Âif event.type == pygame.KEYDOWN:
>>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Âif event.key == pygame.K_UP:
>>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Âsound.frequency += 200
>>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Âif event.key == pygame.K_DOWN:
>>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Âsound.frequency -= 200
>>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Âif event.key == pygame.K_LEFT:
>>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Âif sound.pan <= -0.9:
>>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Âsound.pan = -0.9
>>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Âelse:
>>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Âsound.pan -= 0.1
>>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Âif event.key == pygame.K_RIGHT:
>>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Âif sound.pan >= 0.9:
>>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Âsound.pan = 0.9
>>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Âelse:
>>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Âsound.pan += 0.1
>>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Âif event.key == pygame.K_ESCAPE:
>>> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Âexit()
>>> Â Â Â Â Â Â Â Âclock.tick(10)
>>>
>>> if __name__ == '__main__':
>>> Â Â Â Âmain()
>>>
>>> Thanks,
>>> Ryan
>>>
>> You should use pygame.key.get_pressed() to check whether the left/up keys
>> are pressed. ÂSomething like:
>>
>> while pygame.event.get(): pass
>> key = pygame.key.get_pressed()
>> if key[K_LEFT]: #whatever
>> if key[K_UP]: #whatever
>>
>> Ian
>
> OK, I am seriously confuzzled here. I thought that pygame.event.get()
> gave you all the events, and that his code SHOULD capture multiple
> keypresses.

It gives you all events. You get the even for pressing the first key,
and you get the event for pressing the second key.
You also get the events for releasing those keys later on. You can
keep track of which keys are pressed that way, but pygame does that
for you internally, so you can just get the state of all the keys with
get_pressed, which is more convenient.

> What is the difference between get_pressed and event.get()?

The former gives you the states of all the keys (including keys like
shift and ctrl), the latter gives you an event from the event queue.

> Oh, and would the key repeat be worth doing manually to see if that is
> the issue?

If your game depends on the timing of those repeats, you will most
certainly want to use pygame.Clock and do your own timing, instead of
relying on event.get and the operating system's key repeat.

> soemthing like:
>
> waspressed = []
> thisframepressed = []
>
> every frame:
> Â Â Â Âthisframepressed = []
> Â Â Â Âif event.key in waspressed:
> Â Â Â Â Â Â Â Â## trigger again
> Â Â Â Â Â Â Â Âthisframepressed.append(event.key)
> Â Â Â Âelse:
> Â Â Â Â Â Â Â Âwaspressed.append(event.key)
> Â Â Â Âfor i in waspressed:
> Â Â Â Â Â Â Â Âif not i in thisframepressed:
> Â Â Â Â Â Â Â Â Â Â Â Âwaspressed.remove(i)

No, don't use events for that. Just run your main loop at a constant
FPS with pygame.Clock and check for the key states with get_pressed
regularly. Don't forget to pump the events though, or the window will
become unresponsive.