|
|
|
До этого момента в наших программах для ввода мы пользовалить возможностями 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 
|
|
|