2010-09-18 14 views
5

Chciałbym wiedzieć, jak wykryć naciśnięcie klawisza lub zwolnienie klawisza w pętli while w SDL. Teraz wiem, że możesz uzyskać zdarzenia z SDL, takie jak OnKeyPressed, OnKeyReleased, OnKeyHit, itp., Ale chcę wiedzieć, jak budować funkcje takie jak "KeyPressed", który zwraca boolean, zamiast być zdarzeniem. Przykład:Wejścia w SDL (na naciśnięciu klawisza)

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

Odpowiedz

11

Wiem, że już wybrałeś odpowiedź ... ale tutaj jest jakiś rzeczywisty kod, jak zwykle robię to z jedną tablicą. :)

Najpierw zdefiniuj to gdzieś.

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 

Później, utworzyć funkcję klawiatury(), która będzie rejestrować dane z klawiatury

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 
} 

Potem, gdy rzeczywiście chcesz używać wejścia klawiatury tzn funkcji handleInput() może wyglądać to:

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; 
    } 
} 

I oczywiście można łatwo zrobić to, co chce zrobić

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

** Zaktualizowana wersja na mojej stronie internetowej: ** Dla nie zamieszczając dużo kodu źródłowego, można zobaczyć pełną klawiaturę SDL klasy w C++, który obsługuje

  1. pojedynczego klawisza Wejście
  2. Jednoczesne kombinacje klawiszy (Keys wszystkie wciśnięty w dowolnej kolejności)
  3. Sequential Key Combonations (Keys wszystkie wciśnięty w określonej kolejności)

http://kennycason.com/posts/2009-09-20-sdl-simple-space-shooter-game-demo-part-i.html (jeśli masz jakieś problemy, daj mi znać)

0

Powinieneś mieć 2 tabele booleans na klucze. Jedna tabela, w której ustawiono klucze true lub false w oparciu o zdarzenia keydown/keyup SDL, i inną, która została zainicjowana z wartością false. Podczas sprawdzania keyPressed, porównujesz klucz drugiej tabeli z pierwszym klawiszem tabeli, a jeśli jest inny, jeśli drugi klawisz tabeli ma wartość false, to został naciśnięty, w przeciwnym razie został zwolniony. Następnie wykonaj polecenie secondTable [key]: = not secondTable [key]. Prace!

+0

Po co ci bardzo dziękuję, nie wiem jak docenić twoją pomoc! – deluvas

0

miałem ten problem w LuaJIT z FFI, to jak mogę rozwiązać go:

globalne: kod

KEYS = {} 

zdarzenia:

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 

Aktualizacja funkcji:

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

Większość czasu zmarnowałem na to:

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

Ponieważ FFI wraca obiekt CDATA, który był używany jako array-key, ale potrzebuje całkowitą.

Powiązane problemy