[SDL]Mehrere Tasten gleichzeitig abfragen
-
Hallöchschen leute,
ich hab ein kleines "snake" spiel programmiert. mir hats soweit gut gefallen. dann meine ein kumpel von mir das es toll wäre ein hotseat modus einzufügen.
das war weiter auch nicht sehr schwer. bis auf eine sache, ich kann mir grade nicht erklären wie ich mindestens 2 tasten gleichzeitig abfragen kann.hoffe mir kann jemand helfen.
gruß michi
-
also. Du fragst ja wahrscheinlich mit einer Schleife immer einzeln ab, was gedrückt ist und setzt danach irgendeine Variable z.B. hoch.
danach:
if(button1 == 1 && button2 == 1)
{
mach was;
}oder verstehe ich dein Problem falsch?
-
also immoment sieht das so aus bei mir
while(SDL_PollEvent(&event)) { switch(event.type) { case SDL_QUIT: { app_done = true; menue_done = true; game_done = true; credits_done = true; break; } case SDL_KEYDOWN: { switch( event.key.keysym.sym ) { case SDLK_x: case SDLK_ESCAPE: { app_done = true; menue_done = true; game_done = true; credits_done = true; break; } case SDLK_UP: { player1.move_object(1); break; } case SDLK_DOWN: { player1.move_object(2); break; } case SDLK_LEFT: { player1.move_object(3); break; } case SDLK_RIGHT: { player1.move_object(4); break; } case SDLK_w: { player2.move_object(1); break; } case SDLK_s: { player2.move_object(2); break; } case SDLK_a: { player2.move_object(3); break; } case SDLK_d: { player2.move_object(4); break; } }//Ende Switch(Keys) }//Ende Keydown }//Ende Switch(event.type) }//Ende While Pollevent
-
Füge einfach weitere Abfragen hinzu. Dass zwei Tasten exakt gleichzeitig gedrückt werden, wird sowieso nicht passieren. Schon rein physikalisch nicht...
Edit: Formulierung
-
Bin nicht so vertraut mit der SDL aber vermutlich gibt es das eh schon vorgefertigt...falls nicht:
Du kannst auch ein bool'sches Array[AnzahlDerTasten] anlegen und jedes Mal wenn die Taste gedrückt wird setzt du den entsprechenden Wert auf true - wenn sie losgelassen wird auf false.
Somit kannst du danach abfragen welche Tasten zu diesem Zeitpunkt gedrückt sind.
Also ungefähr so:bool input[size]; while(SDL_PollEvent(&event)) { switch(event.type) { case SDL_QUIT: {} case SDL_KEYDOWN: { switch( event.key.keysym.sym ) { case SDLK_ESCAPE: {input[0]=true;break;} case SDLK_UP: {input[1]=true;break;} case SDLK_DOWN: {input[2]=true;break;} .... }//Ende Switch(Keys) }//Ende Keydown case SDL_KEYUP: { switch( event.key.keysym.sym ) { case SDLK_ESCAPE: {input[0]=false;break;} case SDLK_UP: {input[1]=false;break;} case SDLK_DOWN: {input[2]=false;break;} .... }//Ende Switch(Keys) }//Ende Keyup }//Ende Switch(event.type) }//Ende While Pollevent
Dadurch kannst du später an beliebigen Stellen die Tastatureingaben abfragen ohne unbedingt sofort beim Event darauf reagieren zu müssen.
if(input[1]) // "UP" gedrückt MoveUp();
BTW: Normalerweise sollte es kein Problem sein zwei Tasten gleichzeitig zu drücken aber aufgrund des Tastatur-Aufbaus wirst du merken dass der PC bestimmte Kombinationen nicht verarbeiten kann.
-
Die Funktionalität bietet SDL bereits, nämlich
SDL_GetKeyState()
.
-
Hi,
ich versuche mir momentan auch selbst SDL beizubringen wobei ich auch nicht wirklich viel Erfahrung mit anderen Programmiersprachen habe. Ich habe früh (mit 15 oder so) angefangen mit HTML, PHP und diesem kram, und hab mir das auch soweit ganz gut über die Jahre angeeignet. Aber mit C++ erst vor ca. 2 Monaten begonnen und hab dann vor 2 Wochen auch mit OpenGL angefangen. Die ersten Tage habe ich noch GLUT verwendet aber da man überall nur liest GLUT ist tot, dann gleich mal auf SDL umgesattelt. Find's sogar sehr schick und übersichtlich.
Habe momentan auch das Problem mit KeyEvents. *gg* Mein Code sah genauso aus wie der von "endless" zu beginn des Threads. Habe ihn jetzt ein wenig umgebaut:
void EventKeyHandler() { Uint8 *keystate = SDL_GetKeyState(NULL); if( keystate[ SDLK_ESCAPE]) ManageScreen( true); if( keystate[ SDLK_LMETA] && keystate[ SDLK_q]) Quit = !Quit; }
Das funktioniert soweit jetzt auch ganz gut. ESC lässt das Programm zwischen Vollbild und Fenster switchen und Apfel+Q (Ja hier sitzt ein Apple geschädigter...
) lässt den MainLoop aussteigen und das Programm beenden.
Gibt es einen einfachen weg das ganze nicht mit "if" sondern mit "switch" zu lösen? Ich find "switch" einfach viel cooler...
So, das wäre dann für meinen Ersten Beitrag erstmal alles
Gruß Daniel
-
insanity schrieb:
void EventKeyHandler() { Uint8 *keystate = SDL_GetKeyState(NULL); if( keystate[ SDLK_ESCAPE]) ManageScreen( true); if( keystate[ SDLK_LMETA] && keystate[ SDLK_q]) Quit = !Quit; }
Das funktioniert nicht sonderlich gut. Wenn du zwischen den Abfragen des keystate eine Taste drückst und wieder loslässt kriegt dein Programm das nicht mit.
Für "Apfel - Q", "Esc", "Pause" und ähnliches solltest du bei SDL_KEYDOWN bleiben, das funktioniert auch nach einem Hänger. SDL_GetKeyState ist nur für Spiele geeignet wo man eine Taste gedrückt hält, was bei "Apfel-Q" nicht nötig sein sollte.Edit: Der Effekt sollte auftreten wenn du Esc gedrückt hältst, das Fenster wechselt ständig von Vollbild in Fenstermodus und zurück. Bei einem schnellen Rechner kann es passieren, dass der Nutzer die Esc-Taste nur antippt und das Programm zwei Mal wechselt und nur flackert anstatt zu tun was man will.
Wenn der Rechner ausgelastet ist wird dein Programm sehr träge auf Tastenanschläge reagieren ("Aber ich hab doch Springen gedrückt!!! Wieso springt der nicht!!!").
-
nwp2 schrieb:
Edit: Der Effekt sollte auftreten wenn du Esc gedrückt hältst, das Fenster wechselt ständig von Vollbild in Fenstermodus und zurück. Bei einem schnellen Rechner kann es passieren, dass der Nutzer die Esc-Taste nur antippt und das Programm zwei Mal wechselt und nur flackert anstatt zu tun was man will.
Wenn der Rechner ausgelastet ist wird dein Programm sehr träge auf Tastenanschläge reagieren ("Aber ich hab doch Springen gedrückt!!! Wieso springt der nicht!!!").
Wohl wahr...
Danke, also doch KeyDown und KeyUp mit einem eigenen Array managen?
Dabei wäre GetKeyState doch so schön gewesen. *gg*
Edit: Dann bringt mir GetKeyState ja eigentlich auch nichts wenn ich eine Taste gedrückt halten muss? Weil wenn ich eh den Wert in meinem Array auf 1 setze beim KeyDown und auf 0 bei KeyUp dann hat das doch den selben Effekt? Da kein KeyUp kommt solange ich die Taste gedrückt halte wird auch mein Programm bei jedem durchlauf immer die Taste als gedrückt ansehen oder nicht?
Wenn ich dann die ESC Taste gedrückt halte wird der ja auch bei jedem durchlauf solange kein KeyUp kam den Fenstermodus wechseln? Aber das kann man dann ja verhindern in dem nach dem KeyDown von ESC, der Wert auf 1 gesetzt wird, die Funktion zum Fenstermodus aufgerufen und danach von mir gleich der Wert manuell wieder auf 0 gesetzt wird? Das ich quasi gar nicht erst auf ein KeyUp warte. Zumindest in meinem Kopf macht das grade Sinn, aber ich komme ja auch grade von der Arbeit zur Türe rein...
Gruß Daniel
-
Naja, du machst einfach beim Keydown von Esc den Moduswechsel. Es gibt schon ein Keyrepeat, den kann man ausschalten. Ich kenne SDL nur von pygame, das ist ein Wrapper von SDL für python, da gibt es pygame.key.set_repeat womit man einstellen kann ob man bei gedrückter Taste mehrere Keydowns haben möchte. Du musst nur herausfinden wie die Funktion in nativ SDL heißt (gibs auch für die WinAPI). Dann gibt es nur ein Keydown event egal wie kurz oder lang die Taste gedrückt wird.
Ob du Keydown oder Keymap willst hängt von der Anwendung ab. Prinzipiell ist Keydown sinnvoll wenn beim drücken der Taste einmalig etwas passieren soll, und Keymap wenn gedrückt halten sinnvoll ist. Bei einem Autorennen zum Beispiel sollte Rechts, Links, Gas und Bremse per Keymap realisiert werden, während Menü aufrufen und Perspektive umstellen per Keydown realisiert werden.
Eine eigene Keymap brauchst du nicht, benutze einfach die gegebene Keymap oder Keydown.