netlib.narod.ru< Назад | Оглавление | Далее >

Ядро ввода

Уф! Графическое ядро обширно, и может понадобиться время, чтобы полностью разобраться с ним. А пока давайте отвлечемся и посмотрим на ядро ввода, которое вы будете использовать, чтобы предоставить игрокам возможность управлять программой через клавиатуру, мышь и джойстик.

Устройства ввода представляются двумя простыми классами: cInput и cInputDevice. Класс cInput вы используете для инициализации DirectInput, а класс cInputDevice содержит единственный объект интерфейса устройства DirectInput. Если у вас несколько устройств, используйте отдельные объекты cInputDevice для каждого из них.

Использование DirectInput с cInput

Первый этап использования системы ввода — инициализация DirectInput, являющаяся назначением класса cInput. Класс исключительно компактный, и его объявление выглядит так:

class cInput
{
  protected:
    HWND          m_hWnd; // Дескриптор окна-владельца
    IDirectInput8 *m_pDI; // Интерфейс DirectInput

  public:
    cInput(); // Конструктор
    ~cInput(); // Деструктор

    IDirectInput8 *GetDirectInputCOM();    // Возвращает COM-объект DI
    HWND GethWnd();                        // Возвращает дескриптор окна
    BOOL Init(HWND hWnd, HINSTANCE hInst); // Инициализация класса
    BOOL Shutdown();                       // Освобождение класса
};

Класс cInput исключительно легкий, и вы будете вызывать в нем только две функции (Init и Shutdown). Настоящее волшебство начинается когда вы используете класс cInputDevice.

Устройства ввода и cInputDevice

Класс cInputDevice — вот где происходит настоящая работа. Класс cInputDevice используется для инициализации указанного устройства ввода (клавиатуры, мыши или джойстика) и предоставляет средства получения данных от этого устройства для использования в вашей игре. Класс cInput был простой, а класс cInputDevice сосредотачивает всю остальную функциональность системы ввода, и его объявление выглядит так:

class cInputDevice
{
  public:
    cInput *m_Input;   // Родительский класс cInput
    short m_Type;      // Тип устройства
                       // MOUSE, KEYBOARD,
                       // или JOYSTICK

    IDirectInputDevice8 *m_pDIDevice; // COM-объект устройства

    BOOL m_Windowed;   // TRUE, если используются методы чтения
                       // состояния мыши из Windows или FALSE,
                       // если используются методы DirectInput

    char m_State[256]; // Состояния всех клавиш
                       // и кнопок

    DIMOUSESTATE *m_MouseState;    // Состояние мыши
    DIJOYSTATE   *m_JoystickState; // Состояние джойстика
    BOOL m_Locks[256];             // Флаги блокировки
                                   // клавиш или кнопок

    // Координаты мыши/джойстика
    long m_XPos, m_YPos;

    // Внутренняя функция перечисления
    static BOOL FAR PASCAL EnumJoysticks(
           LPCDIDEVICEINSTANCE pdInst, LPVOID pvRef);

  public:
    cInputDevice();  // Конструктор
    ~cInputDevice(); // Деструктор

    IDirectInputDevice8 *DeviceCOM(); // Возвращает COM-объект

    // Функции для создания интерфейса устройства и его освобождения
    BOOL Create(cInput *Input, short Type,
                BOOL Windowed = TRUE);
    BOOL Free();

    BOOL Clear();                     // Очистка данных устройства
    BOOL Read();                      // Чтение данных устройства
    BOOL Acquire(BOOL Active = TRUE); // Захват или освобождение устройства

    BOOL GetLock(char Num); // Получение состояния блокировки клавиши/кнопки
    BOOL SetLock(char Num, BOOL State = TRUE); // Установка блокировки

    long GetXPos();          // Получаем позицию по x мыши/джойстика
    BOOL SetXPos(long XPos); // Устанавливаем позицию по x
    long GetYPos();          // Получаем позицию по y мыши/джойстика
    BOOL SetYPos(long YPos); // Устанавливаем позицию по y
    long GetXDelta();        // Получаем изменение по x
                             // (относительное перемещение)
    long GetYDelta();        // Получаем изменение по y
                             // (относительное перемещение)

    // Функции, специфичные для клавиатуры
    BOOL GetKeyState(char Num); // Получение состояния клавиши. Возвращает:
                                // TRUE=Нажата или FALSE=Отпущена
                                // Используйте Num = KEY_* или DIK_*
    BOOL SetKeyState(char Num, BOOL State); // Установка состояния клавиши
    BOOL GetPureKeyState(char Num);         // Получение состояния клавиши
                                            //без учета блокировки
    short GetKeypress(long TimeOut = 0);    // Ждем нажатия клавиши
                                            // и возвращаем ASCII-код
    long GetNumKeyPresses();                // Получение количества нажатых
                                            // в данный момент клавиш
    long GetNumPureKeyPresses();            // Получение количества нажатых
                                            // клавиш без учета блокировки

    // Функции, специфичные для мыши/джойстика
    BOOL GetButtonState(char Num);          // Получение состояния кнопок
                                            // Num = LBUTTON, RBUTTON, MBUTTON
    BOOL SetButtonState(char Num, BOOL State); // Установка состояния
    BOOL GetPureButtonState(char Num);      // Получение состояния
                                            // без учета блокировок
    long GetNumButtonPresses();             // Получение количества нажатых
                                            // кнопок
    long GetNumPureButtonPresses();         // Получение количества нажатых
                                            // кнопок без учета блокировок
};

В классе cInpudDevice есть все! Он охватывает все устройства — клавиатуру, мышь и джойстик — в одном удобном пакете. Объект класса начинает работу с вызова cInputDevice::Create, которому передается ранее инициализированный объект класса cInput. Вам надо также сообщить классу с каким устройством вы намереваетесь работать, указав соответствующее значение (KEYBOARD, MOUSE или JOYSTICK) в переменной Type. И, наконец, вам надо уведомить класс желаете ли вы использовать функции чтения состояния устройств из DirectInput или предпочтете методы Windows.

Установка флага Windowed в TRUE заставляет объект класса использовать функции чтения состояния устройств из Windows, в то время, как значение FALSE заставляет использовать DirectInput. Если вы планируете использовать оконный режим (или хотите, чтобы курсор Windows был виден),убедитесь, что для Windowed задали значение TRUE.

Перейдем к списку функций класса: вы вызываете cInputDevice::Read, чтобы прочитать текущее состояние устройства. Затем вы можете проверить состояние каждой отдельной клавиши или кнопки, используя функции cInputDevice::GetKeyState, cInputDevice::GetButtonState, cInputDevice::GetPureKeyState и cInputDevice::GetPureButtonState.

Причина наличия двух наборов функций в том, что клавиши и кнопки могут быть заблокированы. Заблокированная клавиша или кнопка не срабатывает до тех пор, пока не будет отпущена. Чтение чистых значений игнорирует состояние блокировки.

Вызов GetKeyState или GetButtonState возвращает TRUE, если клавиша нажата и FALSE — если нет. Параметр Num в этих функциях проверки состояния представляет проверяемую клавишу или кнопку. На клавиши ссылаются по имени с префиксом KEY_, например, KEY_ESC или KEY_A. Полный список значений KEY_* находится в файле Core_Input.h (или используйте такие константы, как DIK_A и DIK_ESCAPE, предоставляемые DirectInput).

Для ссылки на кнопки мыши используйте значения MOUSE_LBUTTON (левая кнопка), MOUSE_RBUTTON (правая кнопка) и MOUSE_MBUTTON (средняя кнопка). Для джойстика используйте JOYSTICK_BUTTON0, JOYSTICK_BUTTON1, JOYSTICK_BUTTON2, JOYSTICK_BUTTON3, JOYSTICK_BUTTON4 и JOYSTICK_BUTTON5.

Использование ядра ввода

Использовать ядро ввода просто; достаточно создать экземпляр класса cInput и столько объектов cInputDevice, сколько вам нужно, убедившись, что не забыли инициализировать каждый из них. Предположим, вы хотите использовать два устройства — клавиатуру и мышь:

// Глобальные объявления
cInput       g_Input;
cInputDevice g_Keyboard;
cInputDevice g_Mouse;

// Инициализация системы ввода (требуется)
// Предполагается, что hWnd и hInst уже инициализированы
// hWnd = дескриптор окна, hInst = дескриптор экземпляра
g_Input.Init(hWnd, hInst);

// Создаем устройства клавиатуры и мыши
// Для чтения мыши используем методы DirectInput
g_Keyboard.Create(&g_Input, KEYBOARD);
g_Mouse.Create(&g_Input, MOUSE, FALSE);

// Читаем текущее состояние устройств
g_Keyboard.Read();
g_Mouse.Read();

// Если нажата ESC выводим сообщение
if(g_Keyboard.GetKeyState(KEY_ESC) == TRUE) {
    // Блокируем клавишу ESC чтобы пользователь должен был
    // отпустить ее, прежде чем мы снова получим данные о нажатии
    g_Keyboard.SetLock(KEY_ESC, TRUE);
    MessageBox(hWnd, "ESCAPE", "Key Pressed!", MB_OK);
}

// Если нажата левая кнопка мыши, отображаем координаты
if(g_Mouse.GetPureButtonState(MOUSE_LBUTTON) == TRUE) {
    char b[200];
    sprintf(b, "%ld, %ld", g_Mouse.GetXPos(), g_Mouse.GetYPos());
    MessageBox(hWnd, b, "Mouse Coordinates", MB_OK);
}

// Освобождаем все
g_Mouse.Free();
g_Keyboard.Free();
g_Input.Shutdown();

netlib.narod.ru< Назад | Оглавление | Далее >

Сайт управляется системой uCoz