Login
Login-Name Passwort


 
Newsletter
Werbung

Fr, 2. August 2002, 00:00

Multimediaentwicklung mit SDL

Input-Handling: Grundlagen

Marco Kraus

Die libSDL wird gerne als Spielebibliothek verwendet. Dazu ist es aber erforderlich (um überhaupt Spielspass aufkommen zu lassen), dass eine Interaktion zwischen User und Anwendung zustande kommt. SDL bietet dem Entwickler hierfür drei Wege an: Maus, Tastatur und Joystick. Zumindest auf die ersten zwei wollen wir hier nun näher eingehen.

Detail: Tastatur-Handling

SDL kennt zwei Datentypen, welche Tasten repräsentieren. Zum einen den Typ SDLKey. SDLKey ist ein einfacher "enumerated type", der die entsprechenden ASCII-Werte der betätigten Tasten hält. Zum anderen den Typ SDLMod. SDLMod ist rein strukturell und funktional sehr ähnlich, stellt aber die sogenannten Modifiers dar, also z.B. die ALT-, Shift- oder STRG-Taste, wenn sie in Verbindung mit anderen Tasten genutzt werden (z.B. Hotkey-Kombinationen).

Was passiert also nun, wenn eine Taste gedrückt wird?

Zuerst einmal muss man verdeutlichen, dass eigentlich nicht nur das Drücken der Taste wichtig ist, sondern auch das Loslassen. Das Ereignis des Tastendrucks ist also ein anderes als das des Tastenlösens. Daher sprechen wir in Zukunft allgemein von Tastenereignissen. Damit ist dann das Drücken oder das Loslassen gemeint.

Wird nun solch ein Ereignis ausgelöst, so kommen zwei SDL-Strukturen zu tragen: SDL_keysym und SDL_KeyboardEvent. Bei einem Tastenereignis legt SDL die Struktur SDL_KeyboardEvent für genau dieses Ereignis an:

typedef struct {
 Uint8 type;
 Uint8 state;
 SDL_keysym keysym;
} SDL_KeyboardEvent;

Wie man sieht, beschreibt diese Struktur den Status des Events. type und state habe im Prinzip die gleiche Information; nämlich ob das Tastenevent ein "Press" (also ein Tastendruck) oder ein "Release" (Loslassen) war. Wir werden in Zukunft "type" zur Bestimmung des Event befragen. type hat den Wert "SDL_KEYUP" oder "SDL_KEYDOWN".

Mit der kontextlosen Statusinformation des Events können wir nichts anfangen. Daher wird in dieser Struktur des Events noch ein weiteres Element, vom Typ SDL_keysym, angelegt. SDL_keysum ist wie bereits kurz angesprochen wiederum eine Struktur. Diesmal eine Struktur für die eigentlichen Tastenwerte:

typedef struct {
 Uint8 scancode;
 SDLKey sym;
 SDLMod mod;
 Uint16 unicode;
} SDL_keysym;

SDL_keysym speichert die ASCII-Werte der Taste in "sym". Die zugehörigen Modifier-Tasten werden in "mod" abgelegt (Modifiers werden mit konstanten Namen gespeichert, deren Zuweisung in SDL_keysym.h festgelegt ist). Da natürlich bei einem Tastenevent mehrere Modifier zum Tragen kommen können, kann es als sein, dass Konstrukte wie ( KMOD_NUM | KMOD_CAPS | KMOD_LSHIFT ) für mod zustande kommen, was aber nur soviel bedeutet, als dass NumLock, CapsLock und die linke Shift-Taste während dem Tastendruck aktiv waren. Hier gibt es natürlich keine Unterscheidung zwischen Press und Release; entweder ein Modifier war aktiv oder eben nicht.

Scancode ist ein Hardwarescancode, der uns nicht wirklich zu interessieren hat. Der Unicodewert ist beinahe selbsterklärend, wenn auch seine Anwendung ein wenig komplexer erscheint. Unicode ist ein internationaler Zeichensatz. Dies kann also nur funktionieren, wenn eine Taste gedrückt wird. Dieses Feld wird somit nur beim SDL_KEYDOWN korrekt gesetzt. Und auch dann nur, wenn Unicode zuvor über SDL_EnableUnicode() aktiviert wurde. Wir werden Unicode in unseren Beispielen nicht mehr weiter beachten.

Die verschachtelten Strukturen der Keyboardevents werden wohl am besten an folgender Grafik verdeutlicht:

Es wird ersichtlich, dass SDL_KeyboardEvent noch nicht die letzte Station unseres Events war. Es wird noch mit den Strukturen von Maus, Keyboard und Joystick in ein Union vermischt: dem SDL_Event.

Detail: Maus-Handling

Die Eventverarbeitung bei der Maus ist wesentlich simpler als die der Tastatur. Wir müssen eigentlich nur zwei Unterscheidungen machen: MouseMotion und MouseButton. Die Speicherung der Nutzdaten läuft auch hier so ab wie beim Keyboard. Es gibt zwei Strukturen. SDL_MouseMotionEvent für die Mausbewegung und SDL_MouseButtonEvent für die Mausknöpfe. Dort werden die eigentliche Nutzdaten gespeichert:

In SDL_event.h sind diese Mausstrukturen wie folgt definiert:

typedef struct {
 Uint8 type; /* SDL_MOUSEMOTION */
 Uint8 which; /* The mouse device index */
 Uint8 state; /* The current button state */
 Uint16 x, y; /* The X/Y coordinates of the mouse */
 Sint16 xrel; /* The relative motion in the X direction */
 Sint16 yrel; /* The relative motion in the Y direction */
} SDL_MouseMotionEvent;

 

typedef struct {
 Uint8 type; /* SDL_MOUSEBUTTONDOWN or SDL_MOUSEBUTTONUP */
 Uint8 which; /* The mouse device index */
 Uint8 button; /* The mouse button index */
 Uint8 state; /* SDL_PRESSED or SDL_RELEASED */
 Uint16 x, y; /* The X/Y coordinates of the mouse at press time
*/
} SDL_MouseButtonEvent;

Natürlich sind auch diese beiden Strukturen wieder in dem bereits oben erwähnten SDL_Event-Union vorhanden.

SDL_Event

Was das SDL_Surface im SDL_Grafikbereich, ist das SDL_Event im Bereich des Event-Handling. Es ist das zentrale Element, über das auf alle Eventeigenschaften, egal von welchem Eingabegerät, zugegriffen wird. Wird ein Ereignis ausgelöst, so wird von SDL die Struktur des entsprechenden Eingabegerätes gefüttert (z.B. SDL_KeyboardEvent oder auch SDL_MouseMotion und SDL_MouseButton). Diese gerätespezifischen Strukturen sind wiederum alle zusammen in einem SDL_Event-Element vereint.

Für jedes auftretende Ereignis wird ein SDL_Event angelegt und in einem FIFO-Puffer gespeichert. Das heißt konkret, dass ein Pufferspeicher mit SDL_Event-Elementen angelegt wird. Das erste Element, welche in diesen Speicher geschoben wird, ist auch das Element, das später beim Auslesen auch wieder an erster Stelle steht.

Grafisch verdeutlicht sieht das wie folgt aus:

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