2010-09-18 3 views
5

Я хотел бы знать, как я могу обнаружить нажатие клавиши или разблокировку ключа в цикле while в SDL. Теперь я знаю, что вы можете получать события с помощью SDL, например OnKeyPressed, OnKeyReleased, OnKeyHit и т. Д., Но я хочу знать, как создавать такие функции, как «KeyPressed», который возвращает логическое значение, а не событие. Пример:Входы в SDL (по нажатой клавише)

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

ответ

11

Я знаю, что вы уже выбрали ответ .. но вот какой-то фактический код того, как я обычно делаю это с одним массивом. :)

Сначала определите это где-нибудь.

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 

Затем позже, создать функцию клавиатуры(), который будет регистрировать ввод с клавиатуры

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 
} 

Затем, когда вы на самом деле хотите использовать ввод с клавиатуры т.е. функции handleInput(), это может выглядеть примерно так это:

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

И, конечно, вы можете легко делать то, что вы желаете сделать

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

** Обновленная версия на моем сайте: ** Ради не вывешивать много исходного кода, вы можете просмотреть полный SDL класса клавиатуры C++, который поддерживает

  1. Single Key Input
  2. Одновременная Key комбо (Ключи все прессуют в любом порядке)
  3. Последовательная Key Combonations (Keys все прессуют в определенном порядке)

http://kennycason.com/posts/2009-09-20-sdl-simple-space-shooter-game-demo-part-i.html (если у вас есть какие-либо проблемы, дайте мне знать)

0

У вас должно быть 2 таблицы булевых ключей. Одна таблица, в которой вы устанавливаете ключи true или false на основе событий SDK keydown/keyup, а другой - для инициализации с помощью false. При проверке keyPressed вы просто сравниваете второй ключ таблицы с первым ключом таблицы, и если он отличается, если второй ключ таблицы является ложным, то он был нажат, иначе он был выпущен. После этого вы делаете secondTable [key]: = not secondTable [key]. Работает!

+0

Зачем вам большое спасибо, я не знаю, как оценить вашу помощь! – deluvas

0

Я имел эту проблему в LuaJIT с FFI, это то, как я ее решил:

Global: код

KEYS = {} 

события:

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 

функция Update:

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

Большую часть времени я потратил на это:

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

Поскольку FFI возвращает объект CDATA, который был использован в качестве матрицы-ключа, но для этого нужно целое число.

Смежные вопросы