Jump to content
  • Advertisement
Sign in to follow this  
wioneo

Keyboard Input Handling

This topic is 3012 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have been using...

if(SDL_PollEvent(&ev))//in main loop
{do_event(&ev);}
//....
void do_event(SDL_Event* Event);//members of a class
void ev_exit();//functions
void ev_keydown(SDLKey sym, SDLMod mod, Uint16 unicode);
//...........
void c_app::ev_keydown(SDLKey sym, SDLMod mod, Uint16 unicode)
{
switch (sym)
{
case SDLK_ESCAPE: ev_exit();break;
case SDLK_LEFT: /*do stuff*/break;
//.................
}
}
//.........



...to handle all events and keyboard/mouse input, but this method limits me to one keypress(or mouse click I suppose) at a time. That is one unique key not holding down the same key(which is handled with whatever the relevant SDL function is).

So I was thinking that maybe I could use a vector to capture every event each frame and then repeat the event checking code until the list was cleared, but I'm thinking that this might cause a significant slowdown, so what would be a better method to handle key presses? or events in general?

Share this post


Link to post
Share on other sites
Advertisement
I'm not sure what you mean by only one event at a time, but the first thing you'll want to do is to replace your 'if' statement with a 'while' loop, so as to process all pending events each update. (This may fix whatever problem you're describing, but since I'm not clear on the nature of the problem, I can't really say for sure.)

Share this post


Link to post
Share on other sites
Ah that seems silly for me to have overlooked that...but my problem was having multiple actions basedon different events. For example if pressing left rotates a square clockwise and pressing left rotates the square counter-clockwise, pressing both should initiate both actions and they should cancel out each other.

Granted, that specific example is completely useless, but that is the best way for me to convey what I'm thinking. I noticed that I ommitted a large part of the code...

do_event(...)

void c_events::do_event(SDL_Event* Event)
{
switch(Event->type)
{
case SDL_ACTIVEEVENT:
{
switch(Event->active.state)
{
case SDL_APPMOUSEFOCUS:
{
if ( Event->active.gain )
{
ev_mouse_focus();
}
else
{
ev_mouse_blur();
}
break;
}
case SDL_APPINPUTFOCUS:
{
if ( Event->active.gain )
{
ev_input_focus();
}
else
{
ev_input_blur();
}
break;
}
case SDL_APPACTIVE:
{
if ( Event->active.gain )
{
ev_restore();
}
else
{
ev_minimize();
}
break;
}
}
break;
}

case SDL_KEYDOWN:
{
ev_keydown(Event->key.keysym.sym,Event->key.keysym.mod,
Event->key.keysym.unicode);
break;
}

case SDL_KEYUP:
{
ev_keyup(Event->key.keysym.sym,Event->key.keysym.mod,
Event->key.keysym.unicode);
break;
}

case SDL_MOUSEMOTION:
{
ev_mouse_move(Event->motion.x,Event->motion.y,
Event->motion.xrel,Event->motion.yrel,(Event-
>motion.state&SDL_BUTTON(SDL_BUTTON_LEFT))!=0,(Event->motion.state&SDL_BUTTON
(SDL_BUTTON_RIGHT))!=0,(Event->motion.state&SDL_BUTTON(SDL_BUTTON_MIDDLE))!=0);
break;
}

case SDL_MOUSEBUTTONDOWN:
{
switch(Event->button.button)
{
case SDL_BUTTON_LEFT:
{
ev_mouse_ldown(Event->button.x,Event->button.y);
break;
}
case SDL_BUTTON_RIGHT:
{
ev_mouse_rdown(Event->button.x,Event->button.y);
break;
}
case SDL_BUTTON_MIDDLE:
{
ev_mouse_mdown(Event->button.x,Event->button.y);
break;
}
}
break;
}

case SDL_MOUSEBUTTONUP:
{
switch(Event->button.button)
{
case SDL_BUTTON_LEFT:
{
ev_mouse_lup(Event->button.x,Event->button.y);
break;
}
case SDL_BUTTON_RIGHT:
{
ev_mouse_rup(Event->button.x,Event->button.y);
break;
}
case SDL_BUTTON_MIDDLE:
{
ev_mouse_mup(Event->button.x,Event->button.y);
break;
}
}
break;
}

case SDL_JOYAXISMOTION:
{
ev_joy_axis(Event->jaxis.which,Event->jaxis.axis,Event->jaxis.value);
break;
}

case SDL_JOYBALLMOTION:
{
ev_joy_ball(Event->jball.which,Event->jball.ball,
Event->jball.xrel,Event->jball.yrel);
break;
}

case SDL_JOYHATMOTION:
{
ev_joy_hat(Event->jhat.which,Event->jhat.hat,Event->jhat.value);
break;
}
case SDL_JOYBUTTONDOWN:
{
ev_joy_bdown(Event->jbutton.which,Event->jbutton.button);
break;
}

case SDL_JOYBUTTONUP:
{
ev_joy_bup(Event->jbutton.which,Event->jbutton.button);
break;
}

case SDL_QUIT:
{
ev_exit();
break;
}

case SDL_SYSWMEVENT:
{
//Ignore
break;
}

case SDL_VIDEORESIZE:
{
ev_resize(Event->resize.w,Event->resize.h);
break;
}

case SDL_VIDEOEXPOSE:
{
ev_expose();
break;
}

default:
{
ev_user(Event->user.type,Event->user.code,
Event->user.data1,Event->user.data2);
break;
}
}
}



Share this post


Link to post
Share on other sites
Quote:
For example if pressing left rotates a square clockwise and pressing left rotates the square counter-clockwise
Did you mean pressing 'right' rotates the square counter-clockwise?

If so, it's not clear to me from what you've posted why you wouldn't get the desired behavior.

Or are you asking how to tell if a key is currently held down, as opposed to determining when it's pressed and released? If so, you can use the SDL 'get keys' function and poll directly, or you can set a flag (e.g. a 'rotating clockwise' flag) when the corresponding key is pressed, and then clear the flag when it's released.

Share this post


Link to post
Share on other sites
I was just making up something random for an example regarding the clockwise/couter statement.

Right now everything works as expected for keypresses.

However, I want to add the possibility to have multiple *different* key presses per frame. For example if holding up moves forward, and moving left moves toward the left, holding both up and left simultaneously should cause you to move diagonally left of true up.

Right now, if I press left while I was already pressing up, it will stop moving up, and only move left. So whatever the most recent event is is overriding any other event.

I also have 'SDL_EnableKeyRepeat(1, SDL_DEFAULT_REPEAT_INTERVAL);' during initialization to allow holding keys. I don't know exactly what this function affects, though.

Share this post


Link to post
Share on other sites
Make an array of all the keys pressed like:
C#:

bool[] Keysdown = new bool[323];

... in key pressed:
Keysdown[get key number that is down] = true;

... in key released:
Keysdown[get key number that was released] = false;

Sorry if anything is wrong, trying to work off the top of my head and am very tired atm :S

Share this post


Link to post
Share on other sites
Well I hope that the functions that you mentioned will help clean up my code. I managed to get it working suing flags like so...

void c_app::ev_keydown(SDLKey sym, SDLMod mod, Uint16 unicode)
{
switch (sym)
{
case SDLK_ESCAPE: ev_exit();break;
//
case SDLK_w: key_check1|=DOWN_W;break;
case SDLK_s: key_check1|=DOWN_S;break;
//....
}
}
void c_app::ev_keyup(SDLKey sym, SDLMod mod, Uint16 unicode)
{
switch (sym)
{
case SDLK_w: key_check1&=~DOWN_W;break;
case SDLK_s: key_check1&=~DOWN_S;break;
case SDLK_a: key_check1&=~DOWN_A;break;
//..........
}
}
//this runs afetr all event checks
void c_app::check_flags()
{
int ii=1;
if (key_check1 & DOWN_UP){o_camera.inc_coords(0,0,0, -ii,0,0);}
if (key_check1 & DOWN_DOWN){o_camera.inc_coords(0,0,0, +ii,0,0);}
}


...and it works as I was hoping, but requires a lot of extra typing.
I know that you said that you don't have much experience with SDL, but would you have any idea on the performance of 'SDL_GetKeyState' versus bitwise checking? It would be fantastic if the SDL function is slower so that I will have a reason to not go back and erase all of what I'd added.

Share this post


Link to post
Share on other sites
I couldn't say for sure but I'm pretty sure both will be a leap year from becoming a bottleneck. The few times I have profiled my code the rendering is always the big CPU hog. Stuff like input branching doesn't even show up on the charts.

If I were to guess, I guess that your method is at least as fast, assuming the system needs to dispatch input events either way

Share this post


Link to post
Share on other sites
Damn...well at least I learned a bit about flags and such, thank you for the suggestions.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!