Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I have created a cube in opengl using SDL. Now I am trying to move the camera in X direction if user presses left or right arrow keys and Y direction if user presses up or down arrow keys. Right now the camera moves by a fixed amount in a particular direction if the key gets pressed once. It doesn't matter how long does a person hold the key down, it moves by that fixed amount only. I want the camera to move continuously as long as the key is pressed.

Below is the code for keyboard polling.

        while ( SDL_PollEvent( &event ) )
        {
            switch( event.type )
            {
            case SDL_ACTIVEEVENT:
                if ( event.active.gain == 0 )
                isActive = FALSE;
                else
                isActive = TRUE;
                break;              
            case SDL_VIDEORESIZE:
                surface = SDL_SetVideoMode( event.resize.w,
                            event.resize.h,
                            16, videoFlags );
                if ( !surface )
                {
                    fprintf( stderr, "Could not get a surface after resize: %s\n", SDL_GetError( ) );
                    Quit( 1 );
                }
                resizeWindow( event.resize.w, event.resize.h );
                break;
            case SDL_KEYDOWN:
                handleKeyPress( &event.key.keysym );
                break;
            case SDL_QUIT:
                done = TRUE;
                break;
            default:
                break;
            }
        }

And below i have mentioned the keypress handler function

void handleKeyPress( SDL_keysym *keysym )
{
    switch( (keysym->sym) ){
        case SDLK_ESCAPE:
            Quit(0);
            break;
        case SDLK_LEFT:
              eye[0] -= 0.1;
              break;
            case SDLK_RIGHT:
              eye[0] += 0.1;
              break;
            case SDLK_UP:
              eye[1] -= 0.1;
              break;
            case SDLK_DOWN:
              eye[1] += 0.1;
              break;
            default:
              break;
      }

    return;
}

What changes should I make in my code to handle continuous keystroke detection?

Note: The following code does the required job but I don't understand why

if ( ( SDL_EnableKeyRepeat( 100, SDL_DEFAULT_REPEAT_INTERVAL ) ) )
{
        fprintf( stderr, "Setting keyboard repeat failed: %s\n",
             SDL_GetError( ) );
        Quit( 1 );
}
share|improve this question
    
Please consider reviewing some of the questions you've asked and accepting the answers. –  Josh Petrie Nov 9 '11 at 15:55
add comment

4 Answers

up vote 7 down vote accepted
void Main::processInput()
{
    Uint8* keystate = SDL_GetKeyState(NULL);

    //continuous-response keys
    if(keystate[SDLK_LEFT])
    {
    }
    if(keystate[SDLK_RIGHT])
    {
    }
    if(keystate[SDLK_UP])
    {
    }
    if(keystate[SDLK_DOWN])
    {
    }

    //single-hit keys, mouse, and other general SDL events (eg. windowing)
    while(SDL_PollEvent(&event))
    {
        switch (event.type)
        {
            case SDL_MOUSEMOTION:
            break;

            case SDL_QUIT:
            case SDL_KEYDOWN:
                if(event.key.keysym.sym == SDLK_ESCAPE)
                    done = true; //quit
            break;
        }
    }
}

Usage:

Main::Main()
{
    //set up SDL etc.
    //set up timing variables etc.
    timeStepMs = 1000.f / yourUpdateFrequency; //eg. 30Hz
    //set up game world etc.

    //main loop, run like the wind!
    while(!done)
    {

        timeLastMs = timeCurrentMs;
        timeCurrentMs = SDL_GetTicks();
        timeDeltaMs = timeCurrentMs - timeLastMs;
        timeAccumulatedMs += timeDeltaMs;

        while (timeAccumulatedMs >= timeStepMs)
        {
              processInput();
              //update world: do ai, physics, etc. here
              timeAccumulatedMs -= timeStepMs;
        }
        render(); //render update only once
    }
}
share|improve this answer
    
You should call SDL_PumpEvents() before SDL_GetKeyState(), otherwise you're operating on last frame's key state. Alternatively, call SDL_GetKeyState() after the SDL_PollEvents() loop. –  Rhamphoryncus Jun 11 '12 at 2:24
    
while(SDL_PollEvent(&event)) where is event defined? –  Jonathan O Dec 21 '12 at 15:08
    
@JonathanO How about this ;) –  Nick Wiggill Dec 22 '12 at 13:19
    
@NickWiggill: +1 Thanks, the idea helped me do the same in GLFW :) –  legends2k Mar 2 at 11:17
add comment

You're going to want it to read SDL_KEYUP and SDL_KEYDOWN. You can either have it so it sets a boolean to true when the key is pressed and to false when the key is unpressed and then have it check the booleans and perform an action if true, or you can do something like this...

if(SDL_PollEvent(&event)) {
    if(event.type==SDL_KEYDOWN) {
        switch(event.key.keysym.sym) {
            case SDLK_UP:    yVel-=2; break;
            case SDLK_DOWN:  yVel+=2; break;
            case SDLK_LEFT:  xVel-=2; break;
            case SDLK_RIGHT: xVel+=2; break;
        }
    }
    if(event.type==SDL_KEYUP) {
        switch(event.key.keysym.sym) {
            case SDLK_UP:    yVel+=2; break;
            case SDLK_DOWN:  yVel-=2; break;
            case SDLK_LEFT:  xVel+=2; break;
            case SDLK_RIGHT: xVel-=2; break;
        }
    }
}

And then simply add the x/yVel to the x/y position of what you want to move...

x+=xVel;
y+=yVel;
share|improve this answer
add comment

http://www.libsdl.org/cgi/docwiki.cgi/SDL_GetKeyState

share|improve this answer
1  
Please don't answer with just a link to another site. gamedev.stackexchange.com/questions/how-to-answer –  thedaian Nov 9 '11 at 19:49
    
Fair enough - it's just frustrating that this question has come up about 3 times and it's right in the docs. I don't think we should be essentially duplicating external documentation. –  Kylotan Nov 9 '11 at 20:34
1  
Agreed, though your answer would have been better as a comment instead of a full answer in that case. –  thedaian Nov 9 '11 at 20:53
add comment

I don't know exactly how to do it in SDL, but in pseudo code this is the approach

bool[] isKeyDown
bool[] isKeyPressed

public void Check(){
    foreach Key k in Keys
        if(k.isDown && !isKeyDown[k]){
               isKeyDown[k] = true;
               isKeyPressed[k] = true;
        }        
        else if(k.IsDown && isKeyDown[k]){
            isKeyPressed[k] = false;
        }    
        else{
            isKeyDown[k] = false;
            isKeyPressed[k] = false;
        }
    }
}     

This way isKeyPressed[k] is true and only true the first time k was pressed, you can use that for menu navigation. Alternatively isKeyDown[k] is true the entire time that k was pressed.

Now I'm pretty confident that SDL has a way to request the current key state, but if you can only repsond to events you just clear isKeyPressed[k] at the start of every game loop, make isKeyPressed[k] and isKeyDown[k] true on every KeyDown event and make isKeyDown[k] false on every KeyUp event.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.