|
До этого момента в наших программах для ввода мы пользовалить возможностями WinAPI. Да, с его помощью очень просто реализовать поддержку клавиатуры (и даже мышки). Но он не предназначен для игр. Сегодня мы поговорим о том, как использовать в наших программах возможности DirectInput. Это более продвинутый интерфейс для ввода, разработанный Microsoft специально для использования в играх! Вот... итак начнем... За основу для данного урока я взял Урок #3. Так как код этого урока будет не очень маленьким:), то для него рекомендуется завести отдельный исходной файл (*.CPP) , а также потребуется использовать файл заголовка (*.H). Я назвал их Input.cpp и Input.h соответственно. Добавляйте такие файлы в свой проект и приступаем к делу. Сначала разберемся с файлом заголовка (хедером) Input.h: Первым делом добавте в него следующую строку: |
#include <dinput.h> // Заголовочный файл для DirectInput |
Он нам понадобится для доступа ко всем функциям DirectInput'а А теперь создадим удобный для нас класс для работы с ним: |
//----------------------------------------------------------------------------- // Name: class CInput // Desc: Класс для использования DirectInput-устройств //----------------------------------------------------------------------------- class CInput { public: bool Init(HWND hwnd); // Инициализация DirectInput void Shutdown(void); // Удаление DirectInput void Update(void); // Обновление состояний устройств ввода bool isKey(BYTE in_kb); // Проверка кнопки на клавиатуре на нажатость bool isKeyNew(BYTE in_kb); // Проверка кнопки на клавиатуре на новое нажатие bool isMBut(BYTE in_mb); // Проверка кнопки мыши на нажатость bool isMButNew(BYTE in_mb); // Проверка кнопки мыши на новое нажатие float GetMouseSpeedX(void); // Получаем скорость мыши по оси X float GetMouseSpeedY(void); // Получаем скорость мыши по оси Y float GetMouseSpeedZ(void); // Получаем скорость мыши по оси Z (колесико) private: HWND hwnd; LPDIRECTINPUT8 lpDI; // DDX8Input Объект LPDIRECTINPUTDEVICE8 lpDIKeyboard, // Интерфейс клавиатуры lpDIMouse; // Интерфейс мыши BYTE DIks[256]; // Кнопки кла-вы bool kNew[256]; // Новое нажатие DIMOUSESTATE2 DIms; // Состояние мышки bool mbNew[8]; // Новое нажатие }; |
Вот и все! С Input.h закончили. Переходим к главной части нашей программы - Input.cpp В начале файла добавляем: |
#include "Input.h" |
Таким образом, мы включаем текст нашего хедера в текущий файл. Далее мы определяем все методы для нашего класса CInput. Здесь их разбирать не имеет смысла, т.к. все они просты и понятны - просто скачайте исходник! Сейчас же я рассмотрю только главные... Первый метод - функция инициализации CInput::Init(HWND hwnd). При ее вызове мы просто передаем экземпляр нашего окна. Здесь создается DirectInput, а также интерфейсы клавиатуры и мыши. Далее и идет функция, Update. Она вызывается каждый кадр и обновляет состояние клавиатуры и мыши. |
//----------------------------------------------------------------------------- // Name: bool CInput::Update(void) // Desc: Обновление состояния клавиатуры и мыши //----------------------------------------------------------------------------- void CInput::Update(void) { HRESULT hr; // Опрашиваем клавиатуру hr = lpDIKeyboard->GetDeviceState(sizeof(BYTE)*256, &DIks); // Данные с кла-вы if(FAILED(hr)) // Если мы потеряли устройство { do{ hr = lpDIKeyboard->Acquire(); // Пытаемся захватить } while(hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED); } // Опрашиваем мышь hr = lpDIMouse->GetDeviceState(sizeof(DIMOUSESTATE2), &DIms); // Данные с мыши if(FAILED(hr)) // Если мы потеряли устройство { do{ hr = lpDIMouse->Acquire(); // Пытаемся захватить } while(hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED); } } |
Далее мы определяем функции, с помощью которых мы можем получить относительную (относительно предыдущего кадра) скорость мыши: |
//----------------------------------------------------------------------------- // Name: float CInput::GetMouseSpeedX(void) // Desc: Возвращает относительную скорость мыши по оси X //----------------------------------------------------------------------------- float CInput::GetMouseSpeedX(void) { return (float)DIms.lX; } //----------------------------------------------------------------------------- // Name: float CInput::GetMouseSpeedY(void) // Desc: Возвращает относительную скорость мыши по оси Y //----------------------------------------------------------------------------- float CInput::GetMouseSpeedY(void) { return (float)DIms.lY; } //----------------------------------------------------------------------------- // Name: float CInput::GetMouseSpeedZ(void) // Desc: Возвращает относительную скорость мыши по оси Z (колесико) //----------------------------------------------------------------------------- float CInput::GetMouseSpeedZ(void) { return (float)DIms.lZ; } |
А как же нам добраться до наших кнопочек? Вот как: |
//----------------------------------------------------------------------------- // Name: bool CInput::isKey(BYTE in_kb) // Desc: Проверка на нажатие кнопок клавиатуры //----------------------------------------------------------------------------- bool CInput::isKey(BYTE in_kb) { if(DIks[in_kb] & 0x80) return true; else return false; } //----------------------------------------------------------------------------- // Name: bool CInput::isKeyNew(BYTE in_kb) // Desc: Проверка кнопок кла-вы на новое нажатие //----------------------------------------------------------------------------- bool CInput::isKeyNew(BYTE in_kb) { if(DIks[in_kb] & 0x80) { if(kNew[in_kb]){ kNew[in_kb] = false; return true; } } else kNew[in_kb] = true; return false; } //----------------------------------------------------------------------------- // Name: bool CInput::isMBut(BYTE in_mb) // Desc: Проверка на нажатие кнопок мышки //----------------------------------------------------------------------------- bool CInput::isMBut(BYTE in_mb) { if(DIms.rgbButtons[in_mb] & 0x80) return true; else return false; } //----------------------------------------------------------------------------- // Name: bool CInput::isMButNew(BYTE in_mb) // Desc: Проверка кнопок мыши на новое нажатие //----------------------------------------------------------------------------- bool CInput::isMButNew(BYTE in_mb) { if(DIms.rgbButtons[in_mb] & 0x80) { if(mbNew[in_mb]){ mbNew[in_mb] = false; return true; } } else mbNew[in_mb] = true; return false; } |
И теперь нам осталось лишь освободить память из-под DirectInput: |
//----------------------------------------------------------------------------- // Name: bool CInput::Shutdown(void) // Desc: Освобождаем память из-под интерфейса ввода //----------------------------------------------------------------------------- void CInput::Shutdown(void) { if(lpDIKeyboard) lpDIKeyboard->Unacquire(); if(lpDIMouse) lpDIMouse->Unacquire(); if(lpDIKeyboard) lpDIKeyboard->Release(); if(lpDIMouse) lpDIMouse->Release(); if(lpDI) lpDI->Release(); } |
Дааа... теперь как нам все это использовать? открываем наш родной Main.cpp. В начале файла, к списку библиотек добавим |
#pragma comment(lib, "dinput8.lib" ) // Ссылка на dinput8.lib #pragma comment(lib, "dxguid.lib" ) // ССылка на dxguid.lib |
И после всех заголовков добавим: |
#include "Input.h" // Заголовок для использования класса CInput |
теперь, когда мы стали такими крутыми ;) нам больше не нужен старый массив: |
bool keys[256]; // Массив для работы с клавиатурой |
Просто удалите эту строку. И вместо нее напишите: |
CInput Input; // наш класс для работы с кла-вой и мышой через DirectInput |
Теперь переходим в функцию AllInit() |
// Инициируем интерфейс ввода if(!Input.Init(hWnd)) return false; // Если возникла ошибка - выйдем |
А в AllShutdown() освободим его: |
Input.Shutdown(); // Освобождаем интерфейс ввода |
Теперь MsgProc удаляем следующие строки - они нам больше ни к чему: |
case WM_KEYDOWN: // Если нажата клавиша { keys[wParam] = TRUE; return 0; } case WM_KEYUP: // Если клавиша отпущена { keys[wParam] = FALSE; return 0; } |
И сейчас в WinMain вместо |
if(keys[VK_ESCAPE]) isProcess=false; if(keys[VK_F1]) { fullscreen=!fullscreen; //переключаемся в Оконный/полноэкранный режим ResetWindow(Width, Height, fullscreen); } |
Запишим |
Input.Update(); // Обновляем состояние клавиатуры и мышки // Если нажали ESCAPE выходим из цикла if(Input.isKey(DIK_ESCAPE)) isProcess=false; if(Input.isKey(DIK_F1)) // А если F1 { fullscreen=!fullscreen; //переключаемся в Оконный/полноэкранный режим ResetWindow(Width, Height, fullscreen); } |
Фууу...ф... УРА!!! У нас появилась полная поддержка DirectInput! С чем я вас и поздравляю! Кстати исходник качаем ЗДЕСЬ! (~163Kb) Здесь мы просто подключили DirectInput, но вскоре мы полностью насладимся всеми его прелестями... Автор: L1f 
|
|