[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [pygame] key press question
Quoting Robert Flemming <flemming@spiralout.net>:
> So I'm working on my first application and I've got a question. I was
> looking at the newbie guide about the different ways of handling keyboard
> events and I've got a bit of a problem.
[...]
> The problem I found is that
> I'm getting repeating characters. I tinkered with the set_repeat value, but
> that only seems to work when using the event queue. Am I missing something
> obvious here or is that just the way things works?
Robert,
I think this is the way state checking works. I do this for a game I
wrote (Far Blazer)... state checking will tell you if the key is up or
down, but you have to figure out if it was already down or already up
yourself... and if the key is pressed, it will report "pressed" every
time you check.
It would be pretty easy to write a new input method that keeps track
of the keystate, and returns "simulated" key events. This is what I
did.
Here's a piece of code from my Far Blazer's input.py file... yes
it's not elegant, I need to go back and refactor it :-) but it does
work. This just generates one key event for each key that is down. You
might need to do something else instead- generate one particular key
event if two keys are down, for instance.
I handle keyboard repeat rate myself...
. . . . . .
# key state tuple
keystate = None
def get_key_events1():
"""build a list of keydown events by looking at the keyboard
state- we need to do this because we need to be able to handle
having two keys down at the same time.
This routine gets called every tick and has to do a lot of
processing, so it is (somewhat) optimized."""
global keystate
keystate = pygame.key.get_pressed()
# call map_keystate once for each item in all_keys, return a list
# of keys pressed
keys_pressed = map(map_keystate,all_keys)
# call new_key_event for each item in keys_pressed, return a list
# of new key events
new_events = map(new_key_event,keys_pressed)
# filter out the None elements
new_events = filter(lambda x: x != None,new_events)
return new_events
def map_keystate(key):
global keystate
keylaststate = key_last_state[key]
if keystate[key]:
if keylaststate == KEYSTATE_UP:
# key was up last we checked
key_last_state[key] = KEYSTATE_DOWN
return key
#print "keystate down"
else:
# key was down or repeating last we checked
now = pygame.time.get_ticks()
if keylaststate == KEYSTATE_DOWN:
if now - keypress_times[key] > repeat_delay:
keypress_times[key] = now
key_last_state[key] = KEYSTATE_REPEAT
return key
#print "keystate down-repeat"
else: # keylaststate must be KEYSTATE_REPEAT
if now - keypress_times[key] > repeat_interval:
keypress_times[key] = now
return key
#print "keystate repeat"
else:
key_last_state[key] = KEYSTATE_UP
return None
def new_key_event(key):
if key != None:
return(pygame.event.Event(KEYDOWN,{'key':key}))
else:
return None
. . . . .
BTW on my machine this eats up a lot of CPU, but it's the only way I
know for checking if multiple keys are down.
Let me know if this isn't clear, or if it isn't what you are looking
for!
cheers
adam
--
Adam Feuer <adamf@pobox.com> http://www.pobox.com/~adamf/
____________________________________
pygame mailing list
pygame-users@seul.org
http://pygame.seul.org