2015-05-20 1 views
1

я работаю на небольшой игровой движок и не может решить, как иметь дело с вводом с клавиатуры. До сих пор я был обработки ввода с клавиатуры, ловя WM_KEYDOWN и WM_KEYUP сообщения от оконной процедуры, однако это, мне кажется, как не отличное решение для обработки ввода с клавиатуры.игры ввод с клавиатуры и события

Я действительно люблю Infinity Ward 3.0 двигателя, где вы можете легко изменить каждый ключ действие с помощью простого конфигурационного файла или с помощью внутриигровой консоли. Я хотел бы сделать это схоже.

Вот отрывок из конфигурационного файла из IW 3.0 Двигатель:

bind TAB "+scores" 
bind ESCAPE "togglemenu" 
bind SPACE "+gostand" 
bind ALT "gocrouch" 
bind CTRL "goprone" 
bind SHIFT "+breath_sprint" 
bind 1 "weapnext" 
bind 2 "weapnext" 
bind 4 "+smoke" 
bind 5 "+actionslot 3" 
bind 6 "+actionslot 4" 
bind 7 "+actionslot 2" 
bind ` "toggleconsole" 
bind A "+moveleft" 
bind B "mp_QuickMessage" 
bind D "+moveright" 
bind E "+leanright" 

Вы можете даже назначить другие действия для клавиш, как сказать что-то в чате:

bind F3 "say Hello, World!" 

У меня уже есть конфигурационный файл из которого я читаю при запуске игры, и после этого я инициализирую все клавиши действий. Он работает, но действительно неудобно назначать все ключи всем действиям. Для ключей, как A, B, C, D, E ..Это легко, потому что каждый код символов ASCII соответствует WM_KEYDOWN/UP сообщения, но и для ключей, как SPACE, CTRL, SHIFT он не делает.

Так что мои вопросы:

  • Каков наилучший способ поймать ключи? (Raw ввода/окно сообщений/Get (назначить) KeyState)
  • Как я могу сделать это легко для назначения ключей из файла конфигурации для действий?
  • Это хорошая идея, чтобы сделать некоторые менеджера событий?
    • Если да, то как должна выглядеть структура менеджера событий?
  • Должен ли я назначить номера для всех ключей и соответствующих действий, или строки, как "PlayerJump", "PlayerForward", "FireAction" ...?
+1

Q: * «Как я могу [...] назначить X на Y?» * A: использовать ассоциативный контейнер для поиска. – IInspectable

+0

До сих пор я даже не знал, для чего подходит карта! Спасибо! :) – ProXicT

ответ

2

Извините за поздний ответ на нить, я не был дома, последние 2 дня. Я покончил с этой проблемой. По моему первому вопросу, я выбираю необработанный ввод с клавиатурой, и вот код, если кому интересно:

std::map<string, bool> myKey; 
bool KEYBOARD_INPUT::GetRawKeyboardData(LPARAM lParam) 
{ 
    char buffer[sizeof(RAWINPUT)]; 
    UINT size = sizeof(RAWINPUT); 
    GetRawInputData(reinterpret_cast<HRAWINPUT>(lParam), RID_INPUT, buffer, &size, sizeof(RAWINPUTHEADER)); 

    RAWINPUT* raw = reinterpret_cast<RAWINPUT*>(buffer); 
    if(raw->header.dwType == RIM_TYPEKEYBOARD) 
    { 
     const RAWKEYBOARD& rawKeyboard = raw->data.keyboard; 

     unsigned int scanCode = rawKeyboard.MakeCode; 
     unsigned int flags = rawKeyboard.Flags; 
     const bool E0 = ((flags & RI_KEY_E0) != 0); 
     const bool E1 = ((flags & RI_KEY_E1) != 0); 
     const bool KeyDown = !((flags & RI_KEY_BREAK) != 0); 

     UINT key = (scanCode << 16) | (E0 << 24); 
     char buffer[32]; 
     GetKeyNameText((LONG)key, buffer, 32); 
     if(KeyDown) // Press 
     { 
      myKey[buffer] = true; 
     } 
     else // Release 
     { 
      myKey[buffer] = false; 
     } 
    } 
    return true; 
} 

Вот функция для получения фактического нажатия клавиш состояния:

bool KEYBOARD_INPUT::KeyPressed(string key, int mode) 
{ 
    if(mode == ONLYONCE) 
    { 
     if(myKey[key] && pressed_onlyonce[key] == false) 
     { 
      pressed_onlyonce[key] = true; 
      return true; 
     } 
     if(!myKey[key]) 
     { 
      pressed_onlyonce[key] = false; 
      return false; 
     } 
    } 

    else if(mode == CONTINUOUS) 
    { 
     if(myKey[key] == true) 
     { 
      return true; 
     } 
     else 
     { 
      return false; 
     } 
    } 

    else if(mode == TOGGLE) 
    { 
     if(myKey[key] && pressed_toggle[key] == false) 
     { 
      pressed_toggle[key] = true; 
      released_toggle[key] = !released_toggle[key]; 
      return released_toggle[key]; 
     } 
     else if(!myKey[key]) 
     { 
      pressed_toggle[key] = false; 
      return released_toggle[key]; 
     } 
    } 
    return false; 
} 

код также является ответ на мои другие вопросы, я думаю. Если кому-то был интересен полный исходный код для этого класса, дайте мне знать в разделе комментариев.

Я думаю, я могу закрыть эту тему, Мое особое спасибо @IInspectabl, так что спасибо!

-3

Есть много способов. Хороший способ поймать ключи будет с помощью ReadConsoleInput(), а затем обработки ключевых кодов в switch заявления. Как вы видите, в коде ниже вы можете также «связывать» ключи в самом switch заявлении.

#include <stdio.h> 
#include <windows.h> 
#include <iostream> 
using namespace std; 




int main() 
{ 
    DWORD  mode;   /* Preserved console mode */ 
    INPUT_RECORD event;   /* Input event */ 
    BOOL   EXITGAME = FALSE; /* Program termination flag */ 
    unsigned int counter = 0; /* The number of times 'Esc' is pressed */ 


    /* Get the console input handle */ 
    HANDLE hstdin = GetStdHandle(STD_INPUT_HANDLE); 

    /* Preserve the original console mode */ 
    GetConsoleMode(hstdin, &mode); 

    /* Set to no line-buffering, no echo, no special-key-processing */ 
    SetConsoleMode(hstdin, 0); 




    while (!EXITGAME) 
    {   


     if (WaitForSingleObject(hstdin, 0) == WAIT_OBJECT_0) /* if kbhit */ 
     { 
      DWORD count; /* ignored */ 

      /* Get the input event */ 
      ReadConsoleInput(hstdin, &event, 1, &count); 
      cout<<"Key Code = "<<event.Event.KeyEvent.wVirtualKeyCode <<" \n"; 

     } 

      /* Only respond to key release events */ 
      if ((event.EventType == KEY_EVENT) 
      && !event.Event.KeyEvent.bKeyDown) 
      {   


        switch (event.Event.KeyEvent.wVirtualKeyCode) 
        { 
         case VK_ESCAPE: 
          EXITGAME = TRUE; 
         break; 

         case VK_SPACE: 

         break; 


         case VK_RETURN: 

         break; 

         case VK_LEFT: 
          // left key move player left 
          cout<<"VK_LEFT = "<<event.Event.KeyEvent.wVirtualKeyCode <<" \n"; 

         break; 

         case VK_RIGHT: 
          // right key move player right 
          cout<<"VK_RIGHT = "<<event.Event.KeyEvent.wVirtualKeyCode <<" \n"; 

         break;  

         case VK_UP: 
          // up key move player up 
          cout<<"VK_UP = "<<event.Event.KeyEvent.wVirtualKeyCode <<" \n"; 


         break; 

         case VK_DOWN: 
          // up key move player down 
          cout<<"VK_DOWN = "<<event.Event.KeyEvent.wVirtualKeyCode <<" \n"; 


         break; 



        }//switch 

        event.Event.KeyEvent.wVirtualKeyCode=-1;    


     } 
    } 

return 0; 
} 

Список виртуальных клавиш: https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx

ReadConsoleInput: https://msdn.microsoft.com/en-us/library/windows/desktop/ms685035(v=vs.85).aspx

+2

* Игровое устройство * и * консольное приложение * имеют нулевое перекрытие. – IInspectable