Login
Newsletter
Werbung

Fr, 2. August 2002, 00:00

Multimedia-Entwicklung mit SDL Teil 2

Zusammenfassung

Ein SDL_Event ist das eigentliche Eventelement. Jedoch enthält ein SDL_Event die internen Strukturen der Eingabegeräte. Wir müssen daher immer noch zumindest die wichtigsten Elemente der Strukturen von Maus, Joystick und Tastatur kennen, um diese Geräte effektiv verwenden zu können.

Und woher wissen wir als Entwickler nun, in welchen Strukturen die Nutzdaten gespeichert sind? Und welches Gerät hat dieses Event eigentlich ausgelöst? Dies wurde mit dem ersten Element in SDL_Event gelöst. Dies ist "type". Type gibt Auskunft darüber, von welcher Art das Event ist, das in diesem Element gespeichert ist. Folgende Tabelle zeigt die möglichen Einträge mit der entsprechend verantwortlichen Unterstruktur, auf die wir bei benötigten Detailinformationen zugreifen müssen:

Ereignis-NameEreignis-Datentyp
  
SDL_ACTIVEEVENTSDL_ActiveEvent
SDL_KEYDOWN/UPSDL_KeyboardEvent
SDL_MOUSEMOTIONSDL_MouseMotionEvent
SDL_MOUSEBUTTONDOWN/UPSDL_MouseButtonEvent
SDL_JOYAXISMOTIONSDL_JoyAxisEvent
SDL_JOYBALLMOTIONSDL_JoyBallEvent
SDL_JOYHATMOTIONSDL_JoyHatEvent
SDL_JOYBUTTONDOWN/UPSDL_JoyButtonEvent
SDL_QUITSDL_QuitEvent
SDL_SYSWMEVENTSDL_SysWMEvent
SDL_VIDEORESIZESDL_ResizeEvent
SDL_USEREVENTSDL_UserEvent

Die Programmierlogik sollte wie folgt sein: Ein Event legt ein SDL_Event in den Puffer ab. Wir lesen das Event aus und schauen auf den Type. Ist dieser beispielsweise ein SDL_Mousemotion, dann wissen wir, dass es (natürlich) ein MausMotion-Element ist und alle weiteren Mausinformationen (in diesem Falle Position etc.) in SDL_MouseMotionEvent gespeichert sind. Wir greifen dann auf die tieferen Strukturen und Elemente dieser Ereignis-Typen zu.

An letzter Stelle noch die Erklärung zum Auslesen des Puffers. Wir beobachten im Moment nur den obersten Eintrag in der Queue, also das Element, das schon am längsten im Puffer ist. Dies können wir mit zwei Funktionen aus dem Speicher lesen (und somit herauslöschen):

int SDL_PollEvent(SDL_Event *event);
int SDL_WaitEvent(SDL_Event *event);

SDL_PollEvent und SDL_WaitEvent unterscheiden sich von der Funktionalität her nicht. PollEvent ist eben eine aktive Funktion, während WaitEvent passiv auf ein Event wartet.

Es gibt noch einige weitere Funktionen, um den Puffer zu beeinflussen. Beispielweise kann man Filter auf Events setzen, Einträge beobachten ohne zu löschen, manuell neue Elemente in die Queue einfügen oder den Status der einzelnen Events ändern. Die detaillierten Erklärungen gehen aber weit über den Umfang dieses Tutorials hinaus. Die Funktionen sind einfach zu verstehen und in ihrer Anwendung, wenn man die Grundlagen des Input-Handling verstanden hat. Ein Blick in die API-Referenz des Doc-Projects (7) sollte hier eine wertvolle Hilfe sein.

Soweit die Theorie. Kommen wir nun zur ersten Anwendung mit Events.

Input-Handling in der Praxis: Tastatur

Die erste Anwendung nimmt nur unsere Tastatureingaben auf und gibt auf der Standardausgabe den Namen der Tastatur aus. Zusätzlich wird noch mit angegeben, um welchen Tastenstatus es sich handelt.

#include <stdlib.h>
#include "SDL.h"
int main()
{
 SDL_Event event;
 int quit = 0;
 if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
 {
 fprintf( stderr, "Konnte SDL nicht initialisieren: %s\n",
 SDL_GetError() );
 exit( -1 );
 }
 if( SDL_SetVideoMode( 320, 200, 8, SDL_SWSURFACE ) < 0)
 {
 fprintf( stderr, "Konnte video mode nicht setzen: %s\n",
 SDL_GetError() );
 }
 atexit(SDL_Quit);
 while( quit == 0)
 {
 while( SDL_PollEvent( &event ) )
 {
 switch( event.type )
 {
 case SDL_KEYDOWN:
 printf( "Press: " );
 printf( " Name: %s\n", SDL_GetKeyName( event.key.keysym.sym
) );
 break;
 case SDL_KEYUP:
 printf( "Release: " );
 printf( " Name: %s\n", SDL_GetKeyName( event.key.keysym.sym
) );
 break;
 case SDL_QUIT: // SDL_QUIT int ein schliessen des windows
 quit = 1;
 break;
 default:
 break;
 }
 }
 }
 exit( 0 );
}

Detail:

Zuerst wird ein event vom Typ SDL_Event angelegt. Dies ist natürlich unser Union mit den Ereignis-Elementen. Wir initialisieren zuerst SDL, wie wir es bereits in den ersten Kapiteln gemacht haben. Die while-Schleife ist der Beginn des relevanten Code. Hier sind zwei while-Schleifen in einander geschachtelt. Die äußere ist eine einfache Endlosschleife, um ständig von der Tastatur zu lesen. Diese wird abgebrochen, wenn die Variable "quit" auf "1" gesetzt wird. Die innere Schleife holt mittels SDL_PollEvent( &amp;event ) das erste Element aus der Queue. Der Nachfolgende Switch überprüft zu erst den Typ des abgeholten SDL_Event-Elements. Die ersten zwei Anweisungen sind die Fälle, wenn ein Tastendruck erfolgt. Die dritte Anweisung ist ein SDL_QUIT. SDL_QUIT steht im event.type, wenn das SDL-Fenster geschlossen wird.

Bereits in den Tastaturdetails wurde erwähnt, dass event.key.keysym.sym nur die ASCII-Werte der Tasten speichert. Nur wissen die meisten Menschen nicht auswendig, welcher Buchstabe von welchem Wert repräsentiert wird. Um eine lesbare Ausgabe der Tasten zu erzeugen, kann das ASCII-Mapping für die Taste zu Hilfe gezogen werden. Dies wir durch SDL_GetKeyName() realisiert. Die Rückgabe dieser Funktion ist ein in SDL_keysym.h (gehört zu den Standardincludes der libsdl) festegelegter String, also der Name der zugehörigen Taste.

Zu den Modifiers gibt es kein Mapping. Modifiers werden in mod bereits mit einer Konstanten gespeichert. Um dies aussagekräftiger zu machen, wird in der offiziellen Dokumentation folgende Funktion als Lösungsvorschlag gemacht:

void PrintModifiers( SDLMod mod )
{
 printf( "Modifers: " );
 // wenn keine Modifiers aktiviert waren...
 if( mod == KMOD_NONE )
 {
 printf( "None\n" );
 return;
 }
 // Ueberpruefe die Praesenz jedes einzelnen SDLMod-Wertes.
 // Das sieht zwar unsauber aus, aber es gibt keinen besseren Weg.
 if( mod & KMOD_NUM ) printf( "NUMLOCK " );
 if( mod & KMOD_CAPS ) printf( "CAPSLOCK " );
 if( mod & KMOD_LCTRL ) printf( "LCTRL " );
 if( mod & KMOD_RCTRL ) printf( "RCTRL " );
 if( mod & KMOD_RSHIFT ) printf( "RSHIFT " );
 if( mod & KMOD_LSHIFT ) printf( "LSHIFT " );
 if( mod & KMOD_RALT ) printf( "RALT " );
 if( mod & KMOD_LALT ) printf( "LALT " );
 if( mod & KMOD_CTRL ) printf( "CTRL " );
 if( mod & KMOD_SHIFT ) printf( "SHIFT " );
 if( mod & KMOD_ALT ) printf( "ALT " );
 printf( "\n" );
}

Anmerkungen:

Natürlich sollte man auch hier wieder ein Blick in die API-Referenz (7) werfen. Eine Funktion sei aber dennoch hier kurz erwähnt: "SDL_EnableKeyRepeat()". Diese gibt an, ab wann eine gedrückte und gehaltene Taste als Wiederholung dieser gilt.

Um nun Inputhandling an einem richtigen Beispiel zu zeigen, wird im Folgenden die MouseMotion-Ereignisse dazu dienen, unseren Tux über den Bildschirm zu bewegen.

Kommentare (Insgesamt: 0 )
Pro-Linux
Pro-Linux @Facebook
Neue Nachrichten
Werbung