4 >Handling the Keyboard</TITLE
7 CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+
10 TITLE="SDL Library Documentation"
11 HREF="index.html"><LINK
13 TITLE="Input handling"
14 HREF="guideinput.html"><LINK
16 TITLE="Input handling"
17 HREF="guideinput.html"><LINK
20 HREF="guideexamples.html"></HEAD
31 SUMMARY="Header navigation table"
40 >SDL Library Documentation</TH
48 HREF="guideinput.html"
56 >Chapter 3. Input handling</TD
62 HREF="guideexamples.html"
76 NAME="GUIDEINPUTKEYBOARD"
78 >Handling the Keyboard</H1
86 >Keyboard Related Structures</H2
88 >It should make it a lot easier to understand this tutorial is you are familiar with the data types involved in keyboard access, so I'll explain them first.</P
101 > is an enumerated type defined in SDL/include/SDL_keysym.h and detailed <A
107 > symbol represents a key, <TT
110 > corresponds to the 'a' key on a keyboard, <TT
113 > corresponds to the space bar, and so on.</P
124 >SDLMod is an enumerated type, similar to <SPAN
127 >, however it enumerates keyboard modifiers (Control, Alt, Shift). The full list of modifier symbols is <A
128 HREF="sdlkey.html#SDLMOD"
133 > values can be AND'd together to represent several modifiers.</P
144 CLASS="PROGRAMLISTING"
155 > structure describes a key press or a key release. The <TT
160 > field is hardware specific and should be ignored unless you know what your doing. The <TT
168 > value of the key being pressed or released. The <TT
173 > field describes the state of the keyboard modifiers at the time the key press or release occurred. So a value of <TT
175 >KMOD_NUM | KMOD_CAPS | KMOD_LSHIFT</TT
176 > would mean that Numlock, Capslock and the left shift key were all press (or enabled in the case of the lock keys). Finally, the <TT
181 > field stores the 16-bit unicode value of the key.</P
189 >It should be noted and understood that this field is only valid when the <SPAN
192 > is describing a key press, not a key release. Unicode values only make sense on a key press because the unicode value describes an international character and only key presses produce characters. More information on Unicode can be found at <A
193 HREF="http://www.unicode.org"
206 >Unicode translation must be enabled using the <A
207 HREF="sdlenableunicode.html"
210 >SDL_EnableUNICODE</TT
223 >SDL_KeyboardEvent</H3
225 CLASS="PROGRAMLISTING"
230 } SDL_KeyboardEvent;</PRE
234 >SDL_KeyboardEvent</SPAN
235 > describes a keyboard event (obviously). The <TT
248 >SDL_KeyboardEvent</SPAN
254 > field specifies whether the event is a key release (<TT
257 >) or a key press (<TT
265 > is largely redundant, it reports the same information as the <TT
270 > field but uses different values (<TT
281 > contains information of the key press or release that this event represents (see above).</P
291 >Reading Keyboard Events</H2
293 >Reading keybaord events from the event queue is quite simple (the event queue and using it is described <A
296 >). We read events using <A
297 HREF="sdlpollevent.html"
305 > loop and check for <TT
314 > statement, like so:</P
322 >Example 3-10. Reading Keyboard Events</B
325 CLASS="PROGRAMLISTING"
329 /* Poll for events. SDL_PollEvent() returns 0 when there are no */
330 /* more events on the event queue, our while loop will exit when */
332 while( SDL_PollEvent( &event ) ){
333 /* We are only worried about SDL_KEYDOWN and SDL_KEYUP events */
334 switch( event.type ){
336 printf( "Key press detected\n" );
340 printf( "Key release detected\n" );
351 >This is a very basic example. No information about the key press or release is interpreted. We will explore the other extreme out our first full example below - reporting all available information about a keyboard event.</P
360 >A More Detailed Look</H2
362 >Before we can read events SDL must be initialised with <A
368 > and a video mode must be set using <A
369 HREF="sdlsetvideomode.html"
372 >SDL_SetVideoMode</TT
374 >. There are, however, two other functions we must use to obtain all the information required. We must enable unicode translation by calling <TT
376 >SDL_EnableUNICODE(1)</TT
377 > and we must convert <SPAN
380 > values into something printable, using <A
381 HREF="sdlgetkeyname.html"
394 >It is useful to note that unicode values < 0x80 translate directly a characters ASCII value. THis is used in the example below</P
404 >Example 3-11. Interpreting Key Event Information</B
407 CLASS="PROGRAMLISTING"
408 > #include "SDL.h"
410 /* Function Prototypes */
411 void PrintKeyInfo( SDL_KeyboardEvent *key );
412 void PrintModifiers( SDLMod mod );
415 int main( int argc, char *argv[] ){
421 if( SDL_Init( SDL_INIT_VIDEO ) < 0){
422 fprintf( stderr, "Could not initialise SDL: %s\n", SDL_GetError() );
426 /* Set a video mode */
427 if( !SDL_SetVideoMode( 320, 200, 0, 0 ) ){
428 fprintf( stderr, "Could not set video mode: %s\n", SDL_GetError() );
433 /* Enable Unicode translation */
434 SDL_EnableUNICODE( 1 );
436 /* Loop until an SDL_QUIT event is found */
439 /* Poll for events */
440 while( SDL_PollEvent( &event ) ){
442 switch( event.type ){
444 /* Pass the event data onto PrintKeyInfo() */
447 PrintKeyInfo( &event.key );
450 /* SDL_QUIT event (window close) */
468 /* Print all information about a key event */
469 void PrintKeyInfo( SDL_KeyboardEvent *key ){
470 /* Is it a release or a press? */
471 if( key->type == SDL_KEYUP )
472 printf( "Release:- " );
474 printf( "Press:- " );
476 /* Print the hardware scancode first */
477 printf( "Scancode: 0x%02X", key->keysym.scancode );
478 /* Print the name of the key */
479 printf( ", Name: %s", SDL_GetKeyName( key->keysym.sym ) );
480 /* We want to print the unicode info, but we need to make */
481 /* sure its a press event first (remember, release events */
482 /* don't have unicode info */
483 if( key->type == SDL_KEYDOWN ){
484 /* If the Unicode value is less than 0x80 then the */
485 /* unicode value can be used to get a printable */
486 /* representation of the key, using (char)unicode. */
487 printf(", Unicode: " );
488 if( key->keysym.unicode < 0x80 && key->keysym.unicode > 0 ){
489 printf( "%c (0x%04X)", (char)key->keysym.unicode,
490 key->keysym.unicode );
493 printf( "? (0x%04X)", key->keysym.unicode );
497 /* Print modifier info */
498 PrintModifiers( key->keysym.mod );
501 /* Print modifier info */
502 void PrintModifiers( SDLMod mod ){
503 printf( "Modifers: " );
505 /* If there are none then say so and return */
506 if( mod == KMOD_NONE ){
511 /* Check for the presence of each SDLMod value */
512 /* This looks messy, but there really isn't */
514 if( mod & KMOD_NUM ) printf( "NUMLOCK " );
515 if( mod & KMOD_CAPS ) printf( "CAPSLOCK " );
516 if( mod & KMOD_LCTRL ) printf( "LCTRL " );
517 if( mod & KMOD_RCTRL ) printf( "RCTRL " );
518 if( mod & KMOD_RSHIFT ) printf( "RSHIFT " );
519 if( mod & KMOD_LSHIFT ) printf( "LSHIFT " );
520 if( mod & KMOD_RALT ) printf( "RALT " );
521 if( mod & KMOD_LALT ) printf( "LALT " );
522 if( mod & KMOD_CTRL ) printf( "CTRL " );
523 if( mod & KMOD_SHIFT ) printf( "SHIFT " );
524 if( mod & KMOD_ALT ) printf( "ALT " );
538 >I have found that people using keyboard events for games and other interactive applications don't always understand one fundemental point.</P
545 >Keyboard events <SPAN
551 > take place when a keys state changes from being unpressed to pressed, and vice versa.</P
554 >Imagine you have an image of an alien that you wish to move around using the cursor keys: when you pressed the left arrow key you want him to slide over to the left, and when you press the down key you want him to slide down the screen. Examine the following code; it highlights an error that many people have made.
556 CLASS="PROGRAMLISTING"
557 > /* Alien screen coordinates */
558 int alien_x=0, alien_y=0;
561 /* Initialise SDL and video modes and all that */
564 /* Check for events */
565 while( SDL_PollEvent( &event ) ){
566 switch( event.type ){
567 /* Look for a keypress */
569 /* Check the SDLKey values and move change the coords */
570 switch( event.key.keysym.sym ){
592 At first glance you may think this is a perfectly reasonable piece of code for the task, but it isn't. Like I said keyboard events only occur when a key changes state, so the user would have to press and release the left cursor key 100 times to move the alien 100 pixels to the left.</P
594 >To get around this problem we must not use the events to change the position of the alien, we use the events to set flags which are then used in a seperate section of code to move the alien. Something like this:</P
602 >Example 3-12. Proper Game Movement</B
605 CLASS="PROGRAMLISTING"
606 > /* Alien screen coordinates */
607 int alien_x=0, alien_y=0;
608 int alien_xvel=0, alien_yvel=0;
611 /* Initialise SDL and video modes and all that */
614 /* Check for events */
615 while( SDL_PollEvent( &event ) ){
616 switch( event.type ){
617 /* Look for a keypress */
619 /* Check the SDLKey values and move change the coords */
620 switch( event.key.keysym.sym ){
637 /* We must also use the SDL_KEYUP events to zero the x */
638 /* and y velocity variables. But we must also be */
639 /* careful not to zero the velocities when we shouldn't*/
641 switch( event.key.keysym.sym ){
643 /* We check to make sure the alien is moving */
644 /* to the left. If it is then we zero the */
645 /* velocity. If the alien is moving to the */
646 /* right then the right key is still press */
647 /* so we don't tocuh the velocity */
648 if( alien_xvel < 0 )
652 if( alien_xvel > 0 )
656 if( alien_yvel < 0 )
660 if( alien_yvel > 0 )
674 /* Update the alien position */
675 alien_x += alien_xvel;
676 alien_y += alien_yvel;</PRE
679 >As can be seen, we use two extra variables, alien_xvel and alien_yvel, which represent the motion of the ship, it is these variables that we update when we detect keypresses and releases.</P
687 SUMMARY="Footer navigation table"
698 HREF="guideinput.html"
716 HREF="guideexamples.html"
732 HREF="guideinput.html"