SDL:Tutorials:Keyboard Input using an Event Loop

From GPWiki

Files:GUITutorial_warn.gif The Game Programming Wiki has moved! Files:GUITutorial_warn.gif

The wiki is now hosted by GameDev.NET at wiki.gamedev.net. All gpwiki.org content has been moved to the new server.

However, the GPWiki forums are still active! Come say hello.

Hi folks! Welcome to SDL Keyboard Input using an Event Loop, 101. Input is vital to the game playing experience for the following reasons:

  • People do not enjoy games that play themselves.
  • People like being able to type in cool highscore initials like ACE and BUM.
  • People want something to happen when they mash the keyboard in anger.

For these reasons, and more, I suggest you read on!

When setting up SDL, even if you're only interested in keyboard input, you still have to initialize SDL video:

SDL_Surface *screen;
 
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
	printf("Unable to initialize SDL: %s\n", SDL_GetError());
	return 1;
}
 
atexit(SDL_Quit);
 
screen = SDL_SetVideoMode(320, 240, 0, SDL_ANYFORMAT);
if (screen == NULL) {
	printf("Unable to set video mode: %s\n", SDL_GetError());
	return 1;
}

The code above initializes the SDL video mode, and creates a small window which can accept keyboard input when it has focus. Now on to the useful stuff:

SDL_Event event;
int running = 1;
 
while(running) {
	while(SDL_PollEvent(&event)) {
		switch(event.type){
			case SDL_KEYDOWN:
			case SDL_KEYUP:
				DisplayState(&event.key);
				DisplayModifiers(&event.key);
				DisplayKey(&event.key);
				break;
			case SDL_QUIT:
				running = 0;
				break;
		}
	}
}

The code above loops continuously, making calls to SDL_PollEvent repeatedly in order to obtain information on any SDL events which may occur. SDL_PollEvent accepts a pointer to an SDL_Event union, and modifies it to contain information regarding the event. If no events have occurred, SDL_PollEvent will return zero, and the inner while loop will end.

When an event has occurred however, the code within the inner while loop will be executed. The switch takes action based on the value of the SDL_Event's type member, which may be set to a number of different values. Of interest to us now are the following type values:

SDL_KEYDOWN 
Indicates that an SDL_KeyboardEvent event has occurred as the result of a key being pressed.
SDL_KEYUP 
Indicates that an SDL_KeyboardEvent event has as the result of a key being released.
SDL_QUIT 
Indicates that an SDL_QuitEvent event has occurred as the result of the user closing the SDL window.

If the event is of type SDL_QUIT, the running integer will be set to zero, and the outer while loop will finish. On the other hand, if either a SDL_KEYDOWN or SDL_KEYUP event is detected, the DisplayState, DisplayModifiers and DisplayKey functions will be called.

void DisplayState(SDL_KeyboardEvent *key)
{
	if (key->type == SDL_KEYUP)
		printf("RELEASED: ");
	else
		printf("PRESSED: ");
	
}

The DisplayState function accepts a pointer to the SDL_KeyboardEvent member of the SDL_Event and tests the type member of the SDL_KeyboardEvent to determine whether a key press or key release has occurred. The result is displayed with printf.

void DisplayModifiers(SDL_KeyboardEvent *key)
{
	SDLMod modifier = key->keysym.mod;
	if( modifier & KMOD_NUM ) printf( "NUMLOCK " );
	if( modifier & KMOD_CAPS ) printf( "CAPSLOCK " );
	if( modifier & KMOD_MODE ) printf( "MODE " );
	if( modifier & KMOD_LCTRL ) printf( "LCTRL " );
	if( modifier & KMOD_RCTRL ) printf( "RCTRL " );
	if( modifier & KMOD_LSHIFT ) printf( "LSHIFT " );
	if( modifier & KMOD_RSHIFT ) printf( "RSHIFT " );
	if( modifier & KMOD_LALT ) printf( "LALT " );
	if( modifier & KMOD_RALT ) printf( "RALT " );
	if( modifier & KMOD_LMETA ) printf( "LMETA " );
	if( modifier & KMOD_RMETA ) printf( "RMETA " );
}

The DisplayModifiers function accepts a pointer to the SDL_KeyboardEvent member of the SDL_Event and extracts the SDLMod member from it. The SDLMod value is then compared to a number of possible keypress modifier constants to determine which (if any) are currently valid. printf will display the name of any modifiers whose constants have ANDed successfully with the SDLMod value.

void DisplayKey(SDL_KeyboardEvent *key)
{
	printf( "%s\n", SDL_GetKeyName(key->keysym.sym));
}

And finally, the DisplayKey function accepts a pointer to the SDL_KeyboardEvent member of the SDL_Event and extracts the SDL_keysym structure from it to obtain its SDLKey sym value. This SDLKey value is passed to the SDL_GetKeyName function, which returns a string describing the key in question.

The DisplayState, DisplayModifiers and DisplayKey functions will give use a nice description of which keys have been pressed, how they were pressed, and what modifiers were applied.

NOTE: If you're running the code on Windows with Dev-C++, printf may not output to your DOS window. Look for a stdout.txt file to be created in your project directory instead!

Source code

Related Links

SDL Documentation Project - Keyboard Handling

Joel Longanecker's Keyboard Tutorial