简体   繁体   中英

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.

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;

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]) {
    /...
}
//...

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;

在 - while (SDL_PollEvent (&mainEvent)) 之外使用 SDL_GetKeyboardState 捕获,效果很好。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM