# Unable to detect continuous keypress event in SDL

I am developing a game using SDL, and am unable to do continuous motion for my object when a key is held down.

I'm calling SDL_PollEvent() to retrieve all events during a frame, and passing each resulting SDL_Event structure into this function:

void Avatar::handle_input(SDL_Event keyInput){
if( keyInput.type == SDL_KEYDOWN )
{
switch( keyInput.key.keysym.sym )
{
case SDLK_LEFT: Move(1); break;
case SDLK_RIGHT: Move(2); break;
}
}

The problem is that when I hold down the right or left arrow keys, the avatar only moves once instead of moving continuously for as long as I hold down the key. How can I make the motion continue for as long as the key is held down?

An SDL_KEYDOWN event is only sent when the key is first pressed. You will receive an SDL_KEYUP event when it's released.

You'll want to handle moving in code which gets called every frame, not in response to an event. Inside Avatar::handle_input, you'll instead want to set variables to tell you whether each key is up or down, and update those variables as you receive SDL_KEYDOWN and SDL_KEYUP events for those keys.

• I will clarify a bit further. The avatar in my code moves if I press the key and release it and repeat this. But I want the motion to work even if I am keeping the key pressed. I read how events work in SDL but that was not much helpful. Won't the SDL_KEYDOWN event will be called if I keep the key pressed and move the avatar. – Vabs Feb 18 '13 at 5:56
• As I said above, no, SDL_KEYDOWN is only sent when the key changes from 'up' to 'down'. (Similarly, SDL_KEYUP is only sent when it changes from 'down' to 'up'). SDL is only notifying you when a key's state actually changes. If you want to know whether the key is up or down at other times, then you really need to keep track of the most recent status you were informed of (using variables, as I explained in the answer above). – Trevor Powell Feb 18 '13 at 6:16

An event is simply that - an event, and tells you when something has happened, not what the current state is. So you only get one keydown event, when the key first goes down, then a key up event when the key is released again.

For continuous motion, you have 2 choices:

1. Use the events to set your game's internal state. This is the example that Petr Abdulin gives in one answer here, which is an example of what Trevor Powell tells you in another answer.
2. SDL does actually provide a system for tracking which keys are in which state, and you can check this every frame if you want to implement continuous motion during key presses without tracking key states yourself. The function is called SDL_GetKeyState and the documentation is here. You can make these checks in your movement handling function and they should work as you expect.

Trevor is correct, you actually need something like this:

// define vars somewhere
bool left_down;
bool right_down;

void Avatar::handle_input(SDL_Event keyInput)
{
//If a key was pressed
if( keyInput.type == SDL_KEYDOWN )
{
switch( keyInput.key.keysym.sym )
{
case SDLK_LEFT: left_down = true; break;
case SDLK_RIGHT: right_down = true; break;
}
}

if( keyInput.type == SDL_KEYUP )
{
switch( keyInput.key.keysym.sym )
{
case SDLK_LEFT: left_down = false; break;
case SDLK_RIGHT: right_down = false; break;
}
}
}

// somewhere in the update function of game loop
update(/*...*/)
{
if(left_down)
{
Move(1);
}

if(right_down)
{
Move(2);
}
}

The code above does illustrates principle, but is hardly a way to implement it in a nice way. The better way is to have a keys array, which you can address like keys[SDLK_LEFT] and some universal utility functions.