2010-09-18 7 views
5

Je voudrais savoir comment puis-je détecter la pression d'une touche ou la libération d'une touche dans une boucle while en SDL. Maintenant, je sais que vous pouvez obtenir les événements avec SDL comme OnKeyPressed, OnKeyReleased, OnKeyHit, etc, mais je veux savoir comment construire des fonctions comme 'KeyPressed' qui renvoie un booléen, au lieu d'être un événement. Exemple:Entrées en SDL (sur une touche enfoncée)

while not KeyHit(KEY_ESC) 
{ 
//Code here 
} 

Répondre

11

Je sais que vous avez déjà sélectionné une réponse .. mais voici un code réel de la façon dont je le fais généralement avec un tableau. :)

d'abord définir quelque part.

bool KEYS[322]; // 322 is the number of SDLK_DOWN events 

for(int i = 0; i < 322; i++) { // init them all to false 
    KEYS[i] = false; 
} 

SDL_EnableKeyRepeat(0,0); // you can configure this how you want, but it makes it nice for when you want to register a key continuously being held down 

Puis, plus tard, créer une fonction clavier() qui enregistrera l'entrée du clavier

void keyboard() { 
     // message processing loop 
     SDL_Event event; 
     while (SDL_PollEvent(&event)) { 
      // check for messages 
      switch (event.type) { 
       // exit if the window is closed 
      case SDL_QUIT: 
       game_state = 0; // set game state to done,(do what you want here) 
       break; 
       // check for keypresses 
      case SDL_KEYDOWN: 
       KEYS[event.key.keysym.sym] = true; 
       break; 
      case SDL_KEYUP: 
       KEYS[event.key.keysym.sym] = false; 
       break; 
      default: 
       break; 
      } 
     } // end of message processing 
} 

Ensuite, lorsque vous voulez utiliser l'entrée du clavier soit une fonction handleInput(), il peut ressembler à ceci:

void handleInput() { 
    if(KEYS[SDLK_LEFT]) { // move left 
     if(player->x - player->speed >= 0) { 
      player->x -= player->speed; 
     } 
    } 
    if(KEYS[SDLK_RIGHT]) { // move right 
     if(player->x + player->speed <= screen->w) { 
      player->x += player->speed; 
     } 
    } 
    if(KEYS[SDLK_UP]) { // move up 
     if(player->y - player->speed >= 0) { 
      player->y -= player->speed; 
     } 
    } 
    if(KEYS[SDLK_DOWN]) { // move down 
     if(player->y + player->speed <= screen->h) { 
      player->y += player->speed; 
     } 
    } 
    if(KEYS[SDLK_s]) { // shoot 
     if(SDL_GetTicks() - player->lastShot > player->shotDelay) { 
      shootbeam(player->beam); 
     } 
    } 
    if(KEYS[SDLK_q]) { 
     if(player->beam == PLAYER_BEAM_CHARGE) { 
      player->beam = PLAYER_BEAM_NORMAL; 
     } else { 
      player->beam = PLAYER_BEAM_CHARGE; 
     } 
    } 
    if(KEYS[SDLK_r]) { 
     reset(); 
    } 

    if(KEYS[SDLK_ESCAPE]) { 
     gamestate = 0; 
    } 
} 

Et bien sûr, vous pouvez facilement faire ce que vous êtes désireux de faire

while(KEYS[SDLK_s]) { 
    // do something 
    keyboard(); // don't forget to redetect which keys are being pressed! 
} 

** Version mise à jour sur mon site: ** Par souci de ne pas poster beaucoup de code source, vous pouvez voir une classe complète SDL Clavier en C++ qui prend en charge

  1. Entrée clé unique
  2. simultanée touche Combos (touches enfoncées tous dans l'ordre)
  3. séquentielle touche Combonations (touches toutes pressées ordre spécifique)

http://kennycason.com/posts/2009-09-20-sdl-simple-space-shooter-game-demo-part-i.html (si vous avez des problèmes, laissez-moi savoir)

0

Vous devez disposer de 2 tables de booléens pour les clés. Une table, dans laquelle vous définissez les clés true ou false en fonction des événements de keydown/keyup SDL, et une autre, que vous initialisez avec false. Lorsque vous vérifiez keyPressed, vous comparez simplement la deuxième clé de la table avec la première clé de la table, et si elle est différente, si la deuxième clé de la table est fausse, elle est pressée, sinon elle est libérée. Après cela, vous faites secondTable [clé]: = not secondTable [clé]. Travaux!

+0

Pourquoi je vous remercie beaucoup, je ne sais pas comment apprécier votre aide! – deluvas

0

J'ai eu ce problème dans luajit avec IFF, voici comment je l'ai résolu:

mondiale:

KEYS = {} 

Code de l'événement:

ev = ffi.new("SDL_Event[1]") 
function event() 
    while sdl.SDL_PollEvent(ev) ~= 0 do 
     local e = ev[0] 
     local etype = e.type 
     if etype == sdl.SDL_QUIT then 
      return false -- quit 
      -- os.exit() -- prevents interactive mode 
     elseif etype == sdl.SDL_KEYDOWN then 
      if e.key.keysym.sym == sdl.SDLK_ESCAPE then 
       return false -- quit 
       -- os.exit() 
      end 
      print("Pressed: ", e.key.keysym.scancode, "\n") 
      KEYS[tonumber(e.key.keysym.sym)] = true 
      -- print("Pressed: ", (e.key.keysym.sym == sdl.SDLK_w), "\n"); 
     elseif etype == sdl.SDL_KEYUP then 
      KEYS[tonumber(e.key.keysym.sym)] = false 
     elseif etype == sdl.SDL_VIDEORESIZE then 
      -- print("video resize W:".. e.resize.w .. " H:" .. e.resize.h) 
      width = e.resize.w 
      height = e.resize.h 
      onResize() 
     end 
    end 
    return true -- everything ok 
end 

fonction de mise à jour:

if KEYS[sdl.SDLK_w] == true then 
    rot = rot + 1 
end 

La plupart du temps je perdu sur ce point:

KEYS[tonumber(e.key.keysym.sym)] = false 

Parce que IFF retourne un objet CData, qui a été utilisé comme la clé du tableau, mais il a besoin de l'entier.

Questions connexes