Friday, October 14, 2011

Tutorial 5: Using Keyboard and DirectInput

User Input is one of the most important aspects of a game. In this tutorial we will look at using the keyboard through DirectInput
   1: LPDIRECTINPUT8          m_pdInput;
2: LPDIRECTINPUTDEVICE8 m_pdInputKeyboard;
3: BYTE m_cKeyState[256];
4: bool m_bPressedKeys[256];
5: bool m_bLockedKeys[256];
6: HWND m_hWnd;
7: UINT m_iHeight;
8: UINT m_iWidth;
m_pdInput is the input object
m_pdInputKeyboard is the keyboard device
m_cKeyState[] stores the pressed keys on the keyboard
m_bPressedKeys[] is the array of pressed keys on the keyboard
m_bLockedKeys[256] is the array of locked keys on the keyboard
m_hWnd is the handle to the window
1: void cInput::Init( const HINSTANCE hInst,
2: const HWND hWnd,
3: const UINT iTableWidth /*= 0 */,
4: const UINT iTableHeight/*= 0*/ )
5: {
6: m_hWnd = hWnd;
7: 
8: // create the DirectInput Interface
9: DirectInput8Create(hInst, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&m_pdInput, NULL);
10:
  11:     CreateKeyboard();
  12:     ...
  13: }
We first need to create the input object by calling DirectInput8Create()
   1: void cInput::CreateKeyboard()
   2: {
   3:     // create the keyboard device
   4:     m_pdInput->CreateDevice(GUID_SysKeyboard,&m_pdInputKeyboard, NULL);
   5:  
   6:     // set the data format to keyboard format
   7:     m_pdInputKeyboard->SetDataFormat(&c_dfDIKeyboard);
   8:  
   9:     // set the control over the keyboard
  10:     m_pdInputKeyboard->SetCooperativeLevel(m_hWnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);
  11:     DetectKeys();
  12: }
The CreateKeyboard is used to get control over the keyboad. We first create the keyboard device by calling CreateDevice. We set the data format to keyboard format. To get control over the keyboard we now make a call to SetCooperativeLevel and set the flags DISCL_NONEXCLUSIVE and DISCL_FOREGROUND. This basically sets the access level to non-exclusive (i.e other applications can also access the keyboard) and foreground access. By foreground access we mean that the device is automatically un-acquired when the game loses focus.
   1: void cInput::LockKey( const DWORD dwKey )
   2: {
   3:     m_bLockedKeys[dwKey] = true;
   4: }
The LockKey function is used to lock a key on the keyboard so that it is read only once per key press
   1: void cInput::DetectKeys()
   2: {
   3:     m_pdInputKeyboard->Acquire();
   4:  
   5:     m_pdInputKeyboard->GetDeviceState(256, (LPVOID)m_cKeyState);
   6:  
   7:     for (unsigned int iKey=0;iKey<256;iKey++)
   8:     {
   9:         if (m_cKeyState[iKey] & 0x80)
  10:         {
  11:             // key is pressed if it isnt locked
  12:             m_bPressedKeys[iKey] = !(m_bLockedKeys[iKey]);
  13:         }
  14:         else
  15:         {
  16:             m_bPressedKeys[iKey] = false;
  17:             m_bLockedKeys[iKey] = false;
  18:         }
  19:     }
  20: }
The Detectkeys function detects which keys have been pressed. For this we first acquire the keyboard and get the device state. We check which keys have been pressed. A key is considered as pressed only if it is not locked
   1: void cInput::Cleanup()
   2: {
   3:     m_pdInputKeyboard->Unacquire();
   4:     m_pdInputKeyboard->Release();
   5:  
   6:     m_pdInput->Release();
   7: }
Lastly, we have a Cleanup function, which unacquires and releases the input devices

That's all that we need to use the keyboard in our game.The next tutorial will deal with getting mouse input.

No comments :