Tag Archives: sdl2

Keyboard State and Key States

Last updated on September 21st, 2019

In the next chapter we will see how so called events are processed to handle input of any kind (keyboard, mouse, joystick,…) Before that I’d like to introduce a simple, yet powerful way to handle keyboard input.

The keyboard state represents the state (pressed = 1 or unpressed = 0) of all the keyboard keys, hence the key states. By

function SDL_GetKeyboardState(numkeys: PInt): PUInt8

we have easy access to this array.

Keyboard state demo.
The red rectangle can be moved by the WASD keys by reading out their key states.

The following code example will draw a red rectangle which can be moved by the WASD keys. Therefore we read out their key states on every cycle of the program loop.

program SDL_KeyboardState;

uses SDL2;

var
  sdlWindow1: PSDL_Window;
  sdlRenderer: PSDL_Renderer;
  sdlRectangle: TSDL_Rect;
  sdlKeyboardState: PUInt8;
  Running: Boolean = True;

begin

  //initilization of video subsystem
  if SDL_Init(SDL_INIT_VIDEO) < 0 then Halt;

  if SDL_CreateWindowAndRenderer(500, 500, SDL_WINDOW_SHOWN, @sdlWindow1, @sdlRenderer) <> 0
    then Halt;

  // prepare rectangle
  sdlRectangle.x := 250;
  sdlRectangle.y := 250;
  sdlRectangle.w := 10;
  sdlRectangle.h := 10;

  // program loop
  while Running = True do
  begin

    SDL_PumpEvents;
    sdlKeyboardState := SDL_GetKeyboardState(nil);

    // ESC pressed
    if sdlKeyboardState[SDL_SCANCODE_ESCAPE] = 1 then
      Running := False;

    // WASD keys pressed
    if sdlKeyboardState[SDL_SCANCODE_W] = 1 then
      sdlRectangle.y := sdlRectangle.y-1;
    if sdlKeyboardState[SDL_SCANCODE_A] = 1 then
      sdlRectangle.x := sdlRectangle.x-1;
    if sdlKeyboardState[SDL_SCANCODE_S] = 1 then
      sdlRectangle.y := sdlRectangle.y+1;
    if sdlKeyboardState[SDL_SCANCODE_D] = 1 then
      sdlRectangle.x := sdlRectangle.x+1;

    // black background
    SDL_SetRenderDrawColor(sdlRenderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
    SDL_RenderClear(sdlRenderer);
    // draw red rectangle
    SDL_SetRenderDrawColor(sdlRenderer, 255, 0, 0, SDL_ALPHA_OPAQUE);
    SDL_RenderDrawRect(sdlRenderer, @sdlRectangle);

    SDL_RenderPresent(sdlRenderer);
    SDL_Delay(20);
  end;

  // clear memory
  SDL_DestroyRenderer(sdlRenderer);
  SDL_DestroyWindow (sdlWindow1);

  //closing SDL2
  SDL_Quit;

end.

To get the keyboard state, we define a unsigned 8 bit pointer variable sdlKeyboardState in the var clause. It points to the array of key states.

  // program loop
  while Running = True do
  begin

    SDL_PumpEvents;
    sdlKeyboardState := SDL_GetKeyboardState(nil);   

After setting up a SDL2 window and and preparing a SDL2 rectangle, the program loop is entered. Here we need to update the event queue by procedure SDL_PumpEvents. After that we can grab the keyboard state by the former mentioned function SDL_GetKeyboardState. The argument should be nil. These actions have to performed on every cycle.

    // ESC pressed
    if sdlKeyboardState[SDL_SCANCODE_ESCAPE] = 1 then
      Running := False;

    // WASD keys pressed
    if sdlKeyboardState[SDL_SCANCODE_W] = 1 then
      sdlRectangle.y := sdlRectangle.y-1;
    if sdlKeyboardState[SDL_SCANCODE_A] = 1 then
      sdlRectangle.x := sdlRectangle.x-1;
    if sdlKeyboardState[SDL_SCANCODE_S] = 1 then
      sdlRectangle.y := sdlRectangle.y+1;
    if sdlKeyboardState[SDL_SCANCODE_D] = 1 then
      sdlRectangle.x := sdlRectangle.x+1;  

We now can check for the of any key in the array by sdlKeyboardState[SDL_SCANCODE_…] using its
scancode as a handle (e.g. SDL_SCANCODE_ESCAPE for the escape key) and react as desired, e.g. exit the program loop or change the x/y coordinates of the rectangle. The scancode represents the position of the related key state in the array. A detailed description of scancodes in the next chapter. A list of all the scancodes shows all possible scancodes.

← previous Chapter | next Chapter →