13 апреля 2010 в 16:46
Direct3D Урок 06: Использование DirectInput
До этого момента в наших программах для ввода мы пользовалить возможностями WinAPI. Да, с его помощью очень просто реализовать поддержку клавиатуры (и даже мышки). Но он не предназначен для игр. Сегодня мы поговорим о том, как использовать в наших программах возможности DirectInput. Это более продвинутый интерфейс для ввода, разработанный Microsoft специально для использования в играх! Вот... итак начнем...
За основу для данного урока я взял Урок #3.
Так как код этого урока будет не очень маленьким:), то для него рекомендуется завести отдельный исходной файл (*.CPP) , а также потребуется использовать файл заголовка (*.H). Я назвал их Input.cpp и Input.h соответственно. Добавляйте такие файлы в свой проект и приступаем к делу.
Сначала разберемся с файлом заголовка (хедером) Input.h:
Первым делом добавте в него следующую строку:
// Заголовочный файл для DirectInput #include "dinput.h"
Он нам понадобится для доступа ко всем функциям 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!
25 декабря 2017 в 01:14
Всё?
5 октября 2018 в 15:12
Доброго времени суток. Не совсем понятно как получить информацию о повторе нажатии клавиши. Я пробовал на простом примере перемещения некоего объекта по экрану и если ты нажал и держишь клавишу, то объект продолжает постоянно двигаться, а хотелось бы чтобы он двигался только после того как клавиша отпущена и затем нажата снова.
24 марта 2025 в 09:43
Грамматические ошибки русского языка исправьте пожалуйста
авторизуйтесь
или войдите через