SDL multiple key input?

Started by
9 comments, last by mindrot 17 years, 12 months ago
hey, i'm not new to programming but i am new to anything dealing with guis. that said, i've been playing around with SDL the past few days and absolutely love it. anyways, like i said i'm just messing around so i dont have a clear goal, but at the moment i have a little black mage sprite that can run around all over the screen and i just added a jumping feature. my question is this: -say i'm polling key events in a loop, and its currently running forward. -while holding down the arrow key, i press space bar to jump...thats cool everything works fine still -so my sprite is in the air, i've let go of spacebar by now, but gamer instincts say to keep holding down the arrow key. but once i land, its like it forgot all about the arrow key being held down. how can i get SDL to re-recognize a key? i'll put up some code:

while(SDL_PollEvent(&mainEvent)){
   Uint8 *keystates = SDL_GetKeyState( NULL ); //get snapshot
   /*various helper code here (excluded for sake of space)*/
   if (mainEvent.type == SDL_KEYDOWN){
      if (mainEvent.key.keysym.sym == SDLK_RIGHT){
         /*more excluded code here*/
      }
      /*excluded code*/
      else if (mainEvent.key.keysym.sym == SDLK_SPACE){
         /*code that makes my guy jump goes here (excluded)*/
         SDL_Event continueAfterJump;
         continueAfterJump.type = SDL_KEYDOWN;
         if( keystates[SDLK_RIGHT] ){
            continueAfterJump.key.keysym.sym = SDLK_RIGHT;
            SDL_PushEvent(&continueAfterJump);
         }
         else if( keystates[SDLK_LEFT] ){
            continueAfterJump.key.keysym.sym = SDLK_LEFT;
            SDL_PushEvent(&continueAfterJump);
         }
      }
      /*lots more code here, but i think i included all
        that was relevant*/
   }
}



i thought maybe if i force-pushed the event onto the queue it would pick back, but that didnt work. is there maybe someway to force the computer to think the key is up, then force it back down again? any help is appreciated! -larg0 edit: sorry i think i see my error, forgot to rename debugEvent...i'll see if that works edit2: didnt work...i did fix the code in this post though
Advertisement
Put your Key presses into a case statement
Sorta like this

switch(mainEvent.key.keysym.sym){      case SDLK_RIGHT:         /* code for moving right*/         break;      case SDLK_LEFT:         /*code for moving left */         break;      case SDLK_SPACE:         /*code that makes my guy jump goes here (excluded)*/         break;


Just keep 1 event variable. Multiple ones will just be messy.

Hope that works.
-)------ Ed
Instead of using SDL_GetKeyState(), you can poll all of your keyboard events into your own buffered array. When the user presses a key, set the boolean in the array according to the key pressed. When the user releases a key, turn off the boolean.

// Global key bufferbool keys[256];while(SDL_PollEvent(&mainEvent)){   if(mainEvent.type == SDL_KEYDOWN)   {       keys[mainEvent.key.keysym.sym] = true;   }   else if(mainEvent.type == SDL_KEYUP)   {       keys[mainEvent.key.keysym.sym] = false;   }}


And then in your update code, whenever you want to check whether a key is pressed, you can go:
// Update the player positionif( keys[SDLK_RIGHT] )    player.X++;

Using this solution, you let your users have the ability to have more then three keys down at any given time. Good luck!
Rob Loach [Website] [Projects] [Contact]
rob, thats a great solution.
i am already using a similar technique although, i use traditional keyboard polling THEN apply booleans to my sprite velocity.

i never even thought to apply the technique to the event checking itself...

this is going to simplify a lot of code! thanks!
does my update code need to go in the while loop?
i dont think so.
the event poller gathers all the new input since the last cycle
once its processed all the new events, it will break out.
you may think but what if i dont run out of events...like if i were to hold
down a key. but at a few billion calculations ever second there actually is "dead time" inbetween key data and such.

...so no.... your updateGameState() function will go outside of the event poller
Are you basically saying that keystates[SDLK_RIGHT] becomes false even though you don't release that key? If so, that sounds like an SDL bug.
I cannot reproduce this bug (if thats what it is).

Here is my code:

Uint8 *keys = SDL_GetKeyState(NULL);std::string names;for( int i = 0 ; i < SDLK_LAST ; ++i ){    if( keys )    {        SDLKey key = (SDLKey)i;        char *tmp = SDL_GetKeyName(key);        if( tmp != "unknown key" )        {            names += tmp;            names += ' ';        }    }}if( names.empty() ){    //gameState.getConsole()->print( names );    SDL_WM_SetCaption( "No Keys", NULL );}else{    SDL_WM_SetCaption( names.c_str(), NULL );}


Works for me... (right, space, release space and right is still active )
Quote:Original post by Kylotan
Are you basically saying that keystates[SDLK_RIGHT] becomes false even though you don't release that key? If so, that sounds like an SDL bug.


what im saying is that the keyboard doesnt send data as fast as your computer can update. for example, you hold the UP key down and during one cycle, your keyboard manages to send 5 'pulses' of data saying UP key is being pressed!
your processor then nearly instantaneously polles this data and removes it from the queue. now the queue is empty before anymore key data is sent, so the loop breaks and you do the rest of the code... while the rest of the code is being processed your keyboard sends more data saying UP KEY IS PRESSED, and that is added to the event queue, and it gets handled during the next iteration of the main game loop.

There is no true "down state" to a key
if you hold the f key down it doesnt make one long drawn out f======
it makes the following: ffffffffffffffffff
you essentially update your game inbetween the different f's
as far as your processor is concerned it takes hours to type each f
so while holding down your f you get f ----------------------------- f --------------------- f and it uses all the ---- time to update your gamestate

now you may think that would generate fluctuations in update time depending on how ultra your processor is....and your right, on a very minute scale this does cause some speeding up or delay of the game...which is why its good form to include some sort of timer to do updates in pulses. a great example of how to do this is on the libsdl.org introduction page on timers http://www.libsdl.org/intro.en/usingtimers.html found here.

its not 100% accurate, but at least it allows for some degree of cross-machine consistancy
Quote:Original post by cwyers
Quote:Original post by Kylotan
Are you basically saying that keystates[SDLK_RIGHT] becomes false even though you don't release that key? If so, that sounds like an SDL bug.


what im saying is that the keyboard doesnt send data as fast as your computer can update.


If you're handling the keypresses as events, the way it's intended, then this is irrelevant.

Quote:There is no true "down state" to a key


That's not relevant. The state is stored by SDL, and is right there for you to access. The actual electrical signal coming down the wire is irrelevant here. You won't get recurring events for a key you've held down unless you've explicitly asked SDL to do that. While you hold a key down, the value returned by SDL_GetKeyState for that key will stay constant.

This topic is closed to new replies.

Advertisement