SDL - Keyboard Listening
I was moving two rects with SDL. Player 1 on W/S, player 2 on up/down.
Up and down felt fine. But W and S felt like delay.
The loop was this:
c code snippet start
if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_s)
// player 1 down
if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_w)
// player 1 up
if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_DOWN)
// player 2 down
if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_UP)
// player 2 down
c code snippet end
SDL_KEYDOWN fires once when the key goes down. Then nothing, until the OS key-repeat timer starts, usually a few hundred milliseconds later.
That pause is the delay. Holding W does not mean “move every frame”. It means “one event, wait, then more events at the repeat rate”.
SDL already keep a snapshot of every key. SDL_GetKeyboardState returns a pointer to that array. Pump the queue, then index it with a scancode.
c code snippet start
const Uint8 *keys = SDL_GetKeyboardState(NULL);
SDL_StopTextInput();
while (running) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT)
running = 0;
}
if (keys[SDL_SCANCODE_W])
pl1.y -= MOVEMENT_SPEED;
if (keys[SDL_SCANCODE_S])
pl1.y += MOVEMENT_SPEED;
if (keys[SDL_SCANCODE_UP])
pl2.y -= MOVEMENT_SPEED;
if (keys[SDL_SCANCODE_DOWN])
pl2.y += MOVEMENT_SPEED;
SDL_FillRect(surface, NULL, 0);
SDL_FillRect(surface, &pl1, 0xFFFFFF);
SDL_FillRect(surface, &pl2, 0xFFFFFF);
SDL_UpdateWindowSurface(window);
SDL_Delay(16);
}c code snippet end
SDL_SCANCODE_W is the position of the W key. It does not care what letter the layout would emit.
The slot is 1 while the finger is down and 0 on release, so a held key moves every frame. No repeat timer.
The pointer is stable. Call SDL_GetKeyboardState once. The bytes change when you pump events.