C++ und eigene Keyeventhandler
Da ich ja im Moment an der Portierung von Blobby Warriors arbeite und die OpenGL Keyeventhandler fuer meine Zwecke ungenuegend waren, musste ich etwas weiter ausholen, damit alles so laeuft, wie ich es gerne haette. Das Problem an den OpenGL Keyeventhandlern ist, dass sie etwas stoerrisch in Bezug auf Keyrepeating reagieren. Es gibt zwar einen An-/Ausschalter dafuer, jedoch ist der Effekt fuer meine Zwecke nicht zu gebrauchen.
Da ich ein netter Mensch bin (mostly: sein kann), dachte ich mir, dass ich mein Wissen weitergebe. Da ich in der Universitaet meistens mit Java arbeite(n muss), kam ich natuerlich auch mit den Eventhandlern in Java in Kontakt. Der Aufbau erinnerte mich wiederum an die Eventhandler aus C#. Und so ist meiner nun auch aufgebaut. Zumindest gibt es einige Aehnlichkeiten.
Zunaechst habe ich zwei Hilfe-Klassen. Zum ersten die Klasse Key. Mit ihrer Hilfe konfiguriere ich, auf welche Tasten der Eventhandler hoeren soll. Das ist etwas unorthodox, aber Kim hatte das in ActionScript sehr aehnlich gemacht und mir gefiel die Herangehensweise. Zum zweiten habe ich die Klasse KeyList, welche Objekte vom Typ Key speichert. Es ist einfacher eine Liste zu haben, als die einzelnen Key-Objekte herumzuschleppen.
Here we go:
KeyList *keyList = new KeyList(); keyList->Add(LEFT); keyList->Add(RIGHT); keyList->Add(UP); keyList->Add(DOWN);
Hier taucht die Klasse Key nun nicht auf. Das liegt daran, dass die KeyList das intern regelt.
So nun kommt der eigentliche Eventhandler:
KeyEventHandler *keyEventHandler = new KeyEventHandler(keyList); keyEventHandler->SetKeyDownFunction(KeyEventDown); keyEventHandler->SetKeyUpFunction(KeyEventUp);
Hierbei sind KeyEventDown und KeyEventUp Funktionen, die vom Typ void (*keyDownFunction)(unsigned int flag) bzw. void (*keyUpFunction)(unsigned int flag) sind. Die Funktionen habe ich wie folgt implementiert:
void KeyEventDown(unsigned int key) { keyList->GetKeyByFlag(key)->Down(); } void KeyEventUp(unsigned int key) { keyList->GetKeyByFlag(key)->Up(); }
Hinweis: keyList ist oben im Beispiel nicht global definiert. Das ist aber eine Voraussetzung fuer die beiden Callbackfunktionen.
Jetzt kommt der witzige Teil. Da das KeyList-Objekt nur call-by-reference weitergegeben wird, enthaelt es von nun an immer alle konfigurierten Keys mit den noetigen Ist-Gedreuckt-Informationen. Nun besitze ich noch eine Update-Funktion, die in der Hauptschleife des Programms an geeigneter Stelle ausgefuehrt wird. Darin passiert bei mir folgendes:
void Update(KeyList *keyList) { for (int i = 0; i < keyList->Size(); i++) { Key *key = keyList->GetKeyById(i); if (key->IsPressed() || key->HasChanged()) { game->playerBlobby->HandleKeyEvents(key->GetFlag(), key->isPressed, key->duration); } } }
Die mit game beginnende Zeile ist natuerlich Programmspezifisch. Die Funktion dient vor allem der Auswertung der Keystates. Damit der KeyEventHandler die Key-Objekte auch aktualisiert, muss duss die Step()-Methode des KeyEventHandlers (vor der Update-Funktion) ausgefuehrt werden.
Soweit so gut. Ich glaube ich habe nichts vergessen. Hier sind noch die drei angesprochenen Klassen:
Noch eine Anmerkung: Ich verwende glutGet(GLUT_ELAPSED_TIME) als Zeitgeber in Microseconds. Man kann natuerlich auch GetTickCount() oder andere Funktionen nehmen.






