[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