KVASS
KVASS

Reputation: 63

SDL 2.0 Key repeat and delay

I'm having a problem with SDL 2.0 keyboard input in pong-like game. When I order to move to the left by pressing left arrow, it is processed by SDL_PollEvents() and responds correctly if the key was pressed once. However, if I keep the key pressed, I get a short delay (as long as Windows key repeat delay) before moving continuously.

Here is function processing events:

void Event::PlayerEvent (Player &player)
{
    while (SDL_PollEvent (&mainEvent))
    {
        switch (mainEvent.type)
        {
            case SDL_KEYDOWN :
                switch (mainEvent.key.keysym.sym)
                {
                    case SDLK_ESCAPE :
                        gameRunning = false;
                        break;
                    case SDLK_LEFT :
                        player.moving = player.left;
                        break;
                    case SDLK_RIGHT :
                        player.moving = player.right;
                }
                break;
            case SDL_QUIT :
                gameRunning = false;
        }
    }
}

EDIT: After all, I managed to fix this issue by calling SystemParametersInfo (SPI_SETKEYBOARDDELAY, 0, 0, 0) at the start of the program and SystemParametersInfo (SPI_SETKEYBOARDDELAY, 1, 0, 0) at the end, to return to standard key repeat delay.

Upvotes: 6

Views: 12610

Answers (4)

Sandro4912
Sandro4912

Reputation: 351

using SPI_SETKEYBOARDDELAY is not a good approach. This way your game will not be protable anymore since its only available on Windows.

Instead you should use like menthiond in an answer before SDL_GetKeyboardState.

Howeve be aware that you still have to collect the SDL_PollEvent. Otherwise SDL_GetKeyboardState will be always empty.

So it should be like this:

//...
SDL_Event sdlEvent;
while (SDL_PollEvent(&sdlEvent)) {
    if (sdlEvent.type == SDL_QUIT) {
        //..
    }
}

const Uint8* keystates = SDL_GetKeyboardState(NULL);

if(keystates[SDL_SCANCODE_LEFT]) {
    //...
}
if(keystates[SDL_SCANCODE_RIGHT]) {
    /...
}
//...

Upvotes: 1

user9868797
user9868797

Reputation: 1

Use the SDL_GetKeyboardState capturing outside of - while (SDL_PollEvent (&mainEvent)), that works fine.

Upvotes: -3

Phil
Phil

Reputation: 758

simple as that

int vertical = 0;
int horizontal = 0;

float x = 500;
float y = 500;

float speed = 5.0;

in your sdl loop:

    if (SDL_PollEvent(&event))
    {
        switch (event.type)
        {
            case SDL_KEYDOWN:
            {
                switch (event.key.keysym.sym)
                {
                    case SDLK_LEFT:  horizontal=-1; break;
                    case SDLK_RIGHT: horizontal = 1; break;
                    case SDLK_UP:    vertical=-1; break;
                    case SDLK_DOWN:  vertical=+1; break;
                }
                break;
            }
            case SDL_KEYUP:
            {
                switch (event.key.keysym.sym)
                {
                case SDLK_LEFT:  horizontal = 0; break;
                case SDLK_RIGHT: horizontal = 0; break;
                case SDLK_UP:    vertical = 0; break;
                case SDLK_DOWN:  vertical = 0; break;
                }
                break;
            }
        }
    }
    x += horizontal * speed;
    y += vertical * speed;

Upvotes: 0

Jonny D
Jonny D

Reputation: 2344

For game movement, you would typically not use events, but rather use states.

Try using SDL_GetKeyboardState() outside of the event loop:

const Uint8* keystates = SDL_GetKeyboardState(NULL);

...

if(keystates[SDL_SCANCODE_LEFT])
    player.moving = player.left;
else if(keystates[SDL_SCANCODE_RIGHT])
    player.moving = player.right;

Upvotes: 9

Related Questions