游戏项目第9部分:增加输入系统
       
该游戏项目将添加对引擎和主菜单的支持。引擎项目中出现的三个新文件分别是InputInterface.h、DirectInput.h和DirectInput.cpp。

第一个文件InputInterface.h用于定义输入系统和输入设备基类的头文件。每个类都提供了派生类需要实现的默认函数。基类中的每个成员函数都是从DirectInput演示程序中提取出来的相同类。实际上,所有这些代码都很相似。在该输入系统和为演示程序创建的输入系统之间的唯一差别在于该输入系统将事情按照各自的类分开处理,而不是包含在一个巨大的类中一起处理。

InputInterface.h

#ifndef _UGP_INPUT_INTERFACE_H_#define _UGP_INPUT_INTERFACE_H_

// 输入系统基类
class CInputInterface{public:    CInputInterface(){}virtual ~CInputInterface(){}

virtual bool Initialize() = 0;virtual bool UpdateDevices() = 0;

virtual int KeyUp(unsigned int key) = 0;virtual int KeyDown(unsigned int key) = 0;

virtual int MouseButtonUp(unsigned int button) = 0;virtual int MouseButtonDown(unsigned int button) = 0;virtual POINT GetMousePos() = 0;virtual long GetMouseWheelPos() = 0;

virtual int ControllerButtonUp(unsigned int button) = 0;virtual int ControllerButtonDown(unsigned int button) = 0;virtual POINT GetLeftStickPos() = 0;virtual POINT GetRightStickPos() = 0;

virtual void Shutdown() = 0;};

// 输入设备基类
class CDeviceInterface{public:    CDeviceInterface() {}virtual ~CDeviceInterface(){}

virtual bool UpdateDevice() = 0;

virtual int ButtonUp(unsigned int key) = 0;virtual int ButtonDown(unsigned int key) = 0;

virtual POINT GetPosition() = 0;virtual POINT GetZPosition() = 0;

virtual void Shutdown() = 0;};

#endif

  

接下来要介绍的头文件是DirectInput.h。该头文件创建DirectInput类,而DirectInput.cpp实现所有类的函数。定义的第一个类是CKeyboard,后面分别是CMouse和CGameController,最后一个是CDirectInputSystem。

#ifndef _UGP_DIRECTINPUT_H_#define _UGP_DIRECTINPUT_H_

#include<dinput.h>#include"InputInterface.h"#include"defines.h"

class CKeyboard : public CDeviceInterface{public:    CKeyboard(LPDIRECTINPUT8 input, HWND hwnd);~CKeyboard() { Shutdown(); }

bool UpdateDevice();

int ButtonUp(unsigned int key);int ButtonDown(unsigned int key);

    POINT GetPosition();    POINT GetZPosition();

void Shutdown();

// Keyboard device.    LPDIRECTINPUTDEVICE8 m_device;char m_keys[KEYS_SIZE];char m_oldKeys[KEYS_SIZE];};

class CMouse : public CDeviceInterface{public:    CMouse(LPDIRECTINPUT8 input, HWND hwnd, bool exclusive);~CMouse() { Shutdown(); }

bool UpdateDevice();

int ButtonUp(unsigned int key);int ButtonDown(unsigned int key);

    POINT GetPosition();    POINT GetZPosition();

void Shutdown();

// Mouse device.    LPDIRECTINPUTDEVICE8 m_device;    DIMOUSESTATE m_mouseState;    DIMOUSESTATE m_oldMouseState;bool m_button[3];

// Mouse x, y, and wheel position.    long m_xMPos;long m_yMPos;long m_zMPos;

// Max x (width) and y (height)// Restrict means to cap at width/height.    bool m_restrict;int m_width;int m_height;};

class CGameController : public CDeviceInterface{public:    CGameController(LPDIRECTINPUT8 input, HWND hwnd);~CGameController() { Shutdown(); }

bool UpdateDevice();

// Used to create the game controllers.    BOOL EnumDeviceCallBack(const DIDEVICEINSTANCE *inst, void* pData);

int ButtonUp(unsigned int key);int ButtonDown(unsigned int key);

    POINT GetPosition();    POINT GetZPosition();

void Shutdown();

// Game controller device.    LPDIRECTINPUTDEVICE8 m_device;    DIJOYSTATE2 m_gcState;    DIJOYSTATE2 m_oldGCState;char m_name[256];    unsigned long m_numButtons;

// Left and right stick x and y positions.    long m_xGCPos;long m_yGCPos;long m_xGCPos2;long m_yGCPos2;

// Window handled (needed for game controllers).    HWND m_hwnd;

// Copy of input system.    LPDIRECTINPUT8 m_inputSystem;};

class CDirectInputSystem : public CInputInterface{public:    CDirectInputSystem(HWND hwnd, HINSTANCE hInst, bool exclusive);~CDirectInputSystem();

// Init devics, update devices states.    bool Initialize();bool UpdateDevices();

// Keyboard functions.    int KeyUp(unsigned int key);int KeyDown(unsigned int key);

// Mouse functions.    int MouseButtonUp(unsigned int button);int MouseButtonDown(unsigned int button);

// Get mouse position (x, y) and mouse wheel data (z).    POINT GetMousePos();long GetMouseWheelPos();

// Game controller functions.    int ControllerButtonUp(unsigned int button);int ControllerButtonDown(unsigned int button);

// Get controller main (left) and right stick position.    POINT GetLeftStickPos();    POINT GetRightStickPos();

void Shutdown();

protected:    LPDIRECTINPUT8 m_system;

// Devices.    CKeyboard *m_keyboard;    CMouse *m_mouse;    CGameController *m_gameController;};

bool CreateDIInput(CInputInterface **pObj, HWND hwnd, HINSTANCE hInst, bool exclusive);

#endif

  

#include"DirectInput.h"

#pragma comment(lib, "dinput8.lib")#pragma comment(lib, "dxguid.lib")

#define MOUSE_BUFF_SIZE 16

CGameController *gThis = NULL;

bool CreateDIInput(CInputInterface **pObj, HWND hwnd, HINSTANCE hInst, bool exclusive){if(!*pObj) *pObj = new CDirectInputSystem(hwnd, hInst, exclusive);else return false;

return true;}

BOOL gJSEnumDeviceCallBack(const DIDEVICEINSTANCE *inst, void* pData){return gThis->EnumDeviceCallBack(inst, pData);}

CKeyboard::CKeyboard(LPDIRECTINPUT8 input, HWND hwnd){// Initialize the keyboard.    if(input->CreateDevice(GUID_SysKeyboard, &m_device, NULL) == DI_OK)    {if(m_device->SetDataFormat(&c_dfDIKeyboard) == DI_OK)        {if(m_device->SetCooperativeLevel(hwnd,                DISCL_FOREGROUND |DISCL_NONEXCLUSIVE) == DI_OK)            {                m_device->Acquire();            }        }    }

// Clear keys will clear out the array of keys we have.    memset(m_keys, 0, sizeof(m_keys));}

int CKeyboard::ButtonUp(unsigned int key){// If the key in the variable is not pressed then return false.    return (!(m_keys[key] & 0x80) && m_keys[key] != m_oldKeys[key]);}

int CKeyboard::ButtonDown(unsigned int key){// If the key in the variable is not pressed then return false.    return m_keys[key] & 0x80;}

POINT CKeyboard::GetPosition(){// Doesn't have position.    POINT p = { 0, 0 };return p;}

POINT CKeyboard::GetZPosition(){// Doesn't have position.    POINT p = { 0, 0 };return p;}

bool CKeyboard::UpdateDevice(){if(m_device)    {// Save old state for input comparing.        memcpy(m_oldKeys, m_keys, sizeof(m_keys));

// If error getting device state, re-aquire.        if(FAILED(m_device->GetDeviceState(sizeof(m_keys), (LPVOID)m_keys)))        {if(FAILED(m_device->Acquire())) return false;if(FAILED(m_device->GetDeviceState(sizeof(m_keys), (LPVOID)m_keys)))return false;        }    }

return true;}

void CKeyboard::Shutdown(){if(m_device)    {        m_device->Unacquire();        m_device->Release();        m_device = NULL;    }}

CMouse::CMouse(LPDIRECTINPUT8 input, HWND hwnd, bool exclusive){// Initialize the Mouse.    DWORD flags;

if(input->CreateDevice(GUID_SysMouse, &m_device, NULL) == DI_OK)    {if(m_device->SetDataFormat(&c_dfDIMouse) == DI_OK)        {if(exclusive) flags = DISCL_FOREGROUND | DISCL_EXCLUSIVE | DISCL_NOWINKEY;else flags = DISCL_FOREGROUND | DISCL_NONEXCLUSIVE;

if(m_device->SetCooperativeLevel(hwnd, flags) == DI_OK)            {                m_device->Acquire();            }        }    }}

int CMouse::ButtonUp(unsigned int button){// If the button is not clicked we return false.    return (!(m_mouseState.rgbButtons[button] & 0x80) &&        m_mouseState.rgbButtons[button] != m_oldMouseState.rgbButtons[button]);}

int CMouse::ButtonDown(unsigned int button){// If the button is clicked we return true.    return m_mouseState.rgbButtons[button] & 0x80;}

bool CMouse::UpdateDevice(){// Get the device state.    if(m_device)    {// Save old state for input comparing.        memcpy(&m_oldMouseState, &m_mouseState, sizeof(m_mouseState));

// If error getting device state, re-aquire.        if(FAILED(m_device->GetDeviceState(sizeof(DIMOUSESTATE), &m_mouseState)))        {if(FAILED(m_device->Acquire())) return false;if(FAILED(m_device->GetDeviceState(sizeof(DIMOUSESTATE), &m_mouseState)))return false;        }

        m_xMPos += m_mouseState.lX;        m_yMPos += m_mouseState.lY;        m_zMPos = m_mouseState.lZ;    }

return true;}

POINT CMouse::GetPosition(){    POINT pos;

    pos.x = m_xMPos;    pos.y = m_yMPos;return pos;}

POINT CMouse::GetZPosition(){    POINT p = { m_zMPos, m_zMPos };return p;}

void CMouse::Shutdown(){if(m_device)    {        m_device->Unacquire();        m_device->Release();        m_device = NULL;    }}

CGameController::CGameController(LPDIRECTINPUT8 input, HWND hwnd){// Save copies.    gThis = this;    m_hwnd = hwnd;    m_inputSystem = input;

// Initialize the game controller.    DIPROPRANGE range;    DIDEVCAPS caps;

    m_inputSystem->EnumDevices(DI8DEVCLASS_GAMECTRL, (LPDIENUMDEVICESCALLBACK)gJSEnumDeviceCallBack,        NULL, DIEDFL_ATTACHEDONLY);

if(m_device)    {        range.diph.dwSize = sizeof(DIPROPRANGE);        range.diph.dwHeaderSize = sizeof(DIPROPHEADER);        range.diph.dwHow = DIPH_BYOFFSET;        range.lMin = -1000;        range.lMax = 1000;        range.diph.dwObj = DIJOFS_X;        m_device->SetProperty(DIPROP_RANGE, &range.diph);        range.diph.dwObj = DIJOFS_Y;        m_device->SetProperty(DIPROP_RANGE, &range.diph);

if(SUCCEEDED(m_device->GetCapabilities(&caps))) m_numButtons = caps.dwButtons;else m_numButtons = 4;    }}

BOOL CGameController::EnumDeviceCallBack(const DIDEVICEINSTANCE *inst, void* pData){// Set to the first device found.    if(SUCCEEDED(m_inputSystem->CreateDevice(inst->guidInstance, &m_device, NULL)))    {if(SUCCEEDED(m_device->SetDataFormat(&c_dfDIJoystick2)))if(SUCCEEDED(m_device->SetCooperativeLevel(m_hwnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE)))if(SUCCEEDED(m_device->Acquire()))                {                    strcpy(m_name, (char*)inst->tszProductName);return DIENUM_STOP;                }    }

// Return continue to try to init other connected devices.    return DIENUM_CONTINUE;}

int CGameController::ButtonUp(unsigned int button){if(button < 0 || button >= m_numButtons) return 0;return (!(m_gcState.rgbButtons[button] & 0x80) &&        m_gcState.rgbButtons[button] != m_oldGCState.rgbButtons[button]);}

int CGameController::ButtonDown(unsigned int button){if(button < 0 || button >= m_numButtons) return 0;return m_gcState.rgbButtons[button] & 0x80;}

bool CGameController::UpdateDevice(){if(m_device)    {        m_device->Poll();

// Save old state for input comparing.        memcpy(&m_oldGCState, &m_gcState, sizeof(m_gcState));

// If error getting device state, re-aquire.        if(FAILED(m_device->GetDeviceState(sizeof(DIJOYSTATE2), &m_gcState)))        {if(FAILED(m_device->Acquire())) return false;if(FAILED(m_device->GetDeviceState(sizeof(DIJOYSTATE2), &m_gcState)))return false;        }

        m_xGCPos = m_gcState.lX;        m_yGCPos = m_gcState.lY;

        m_xGCPos2 = m_gcState.lZ;        m_yGCPos2 = m_gcState.lRz;    }

return true;}

POINT CGameController::GetPosition(){    POINT pos;

    pos.x = m_xGCPos;    pos.y = m_yGCPos;return pos;}

POINT CGameController::GetZPosition(){    POINT pos;

    pos.x = m_xGCPos2;    pos.y = m_yGCPos2;return pos;}

void CGameController::Shutdown(){if(m_device)    {        m_device->Unacquire();        m_device->Release();        m_device = NULL;    }}

CDirectInputSystem::CDirectInputSystem(HWND hwnd, HINSTANCE hInst, bool exclusive){// Initialize objects...    m_keyboard = NULL;    m_mouse = NULL;    m_gameController = NULL;

// Create input system.    if(DirectInput8Create(hInst, DIRECTINPUT_VERSION,        IID_IDirectInput8, (void **)&m_system, NULL) == DI_OK)    {        m_keyboard = new CKeyboard(m_system, hwnd);        m_mouse = new CMouse(m_system, hwnd, exclusive);        m_gameController = new CGameController(m_system, hwnd);    }}

CDirectInputSystem::~CDirectInputSystem(){// Shut everything down.    Shutdown();}

bool CDirectInputSystem::Initialize(){// Everything took place in the constructor.// Force keyboard and mouse before considering the// system initialized.    return (m_keyboard && m_mouse);}

bool CDirectInputSystem::UpdateDevices(){int hr;

// Get the device state.    if(m_mouse) hr = m_mouse->UpdateDevice();if(m_keyboard) hr = m_keyboard->UpdateDevice();if(m_gameController) hr = m_gameController->UpdateDevice();

return true;}

int CDirectInputSystem::KeyUp(unsigned int key){if(!m_keyboard) return 0;return m_keyboard->ButtonUp(key);}

int CDirectInputSystem::KeyDown(unsigned int key){if(!m_keyboard) return 0;return m_keyboard->ButtonDown(key);}

int CDirectInputSystem::MouseButtonUp(unsigned int button){if(!m_mouse) return 0;return m_mouse->ButtonUp(button);}

int CDirectInputSystem::MouseButtonDown(unsigned int button){if(!m_mouse) return 0;return m_mouse->ButtonDown(button);}

int CDirectInputSystem::ControllerButtonUp(unsigned int button){if(!m_gameController) return 0;return m_gameController->ButtonUp(button);}

int CDirectInputSystem::ControllerButtonDown(unsigned int button){if(!m_gameController) return 0;return m_gameController->ButtonDown(button);}

POINT CDirectInputSystem::GetMousePos(){    POINT null = {0, 0};if(!m_mouse) return null;

return m_mouse->GetPosition();}

long CDirectInputSystem::GetMouseWheelPos(){if(!m_mouse) return 0;

    POINT wheel =  m_mouse->GetZPosition();return wheel.y;}

POINT CDirectInputSystem::GetLeftStickPos(){    POINT null = {0, 0};if(!m_gameController) return null;

return m_gameController->GetPosition();}

POINT CDirectInputSystem::GetRightStickPos(){    POINT null = {0, 0};if(!m_gameController) return null;

return m_gameController->GetZPosition();}

void CDirectInputSystem::Shutdown(){// Delete each object...    if(m_keyboard)    {        m_keyboard->Shutdown();        delete m_keyboard;        m_keyboard = NULL;    }

if(m_mouse)    {        m_mouse->Shutdown();        delete m_mouse;        m_mouse = NULL;    }

if(m_gameController)    {        m_gameController->Shutdown();        delete m_gameController;        m_gameController = NULL;    }

if(m_system)    {        m_system->Release();        m_system = NULL;    }}

  游戏项目中还包含了DirectInput的头文件和源文件。在源文件中的g_Render后面添加了一个全局指针变量,用于实现输入检测。程序清单10.28给出了main源文件全局部分的完整代码。同渲染系统一样,输入系统使用的是基类。初始化引擎时,要为所要使用的输入系统分配内存。

#include"main.h"

// 窗口句柄

HWND g_hwnd;

HINSTANCE g_hInstance;   // 程序的当前实例的句柄

CInputInterface *g_InputSystem = NULL;   // 输入系统的抽象基类

// 渲染基类的对象指针 g_Render

CRenderInterface* g_Render = NULL;

// GUI控件ID

int g_mainGui = -1;     // 主菜单界面

int g_startGui = -1;    // 开始菜单界面

int g_creditsGui = -1;  // 字幕菜单界面

int g_currentGUI = GUI_MAIN_SCREEN;   // 当前菜单界面

// 字体类型ID

int g_arialID = -1;

// 鼠标的状态信息

bool LMBDown = false;    // 光标左键是否按下

bool LMBUp = false;      // 鼠标左键是否弹起

int mouseX = 0, mouseY = 0;   // 鼠标指针位置(X和Y)

游戏项目中的最后几个函数分别是InitializeEngine()、Shutdown()、ProcessInput()和GameLoop()。InitializeEngine()函数必须初始化输入系统,因为它现在已经成为引擎自身的一部分。诚如所知,Shutdown()函数在完成工作之后通过释放所有的对象来“清除垃圾”。ProcessInput()函数用于处理游戏程序所需的输入,就目前而言,主要是记录鼠标位置、确定按钮是否被按下,以及对按下的Esc键作为响应。GameLoop()函数简短而扼要。在进入主菜单并对它做一些改动之前,GameLoop()函数会调用ProcessInput()函数,以更新程序中的所有输入。
// 创建渲染系统对象,并初始化Direct3Dbool InitializeEngine(){// g_Render指向创建的渲染系统抽象基类对象    if (! CreateD3DRenderer(&g_Render) )    {return false;    }

// 渲染系统初始化Direct3D    if (! g_Render->Initialize(WIN_WIDTH, WIN_HEIGHT, g_hwnd, FULLSCREEN, UGP_MS_SAMPLES_4) )    {return false;    }

// 设置后台缓存的指定清除色    g_Render->SetClearCol(0, 0, 0);

// 为要显示的文本创建Arial字体    if (! g_Render->CreateText("Arial", 0, true, 18, g_arialID) )    {return false;    }

// 动态开辟输入系统CDirectInputSystem类对象    if (! CreateDIInput(&g_InputSystem, g_hwnd, g_hInstance, false) )    {return false;    }

// 输入系统初始化    if (! g_InputSystem->Initialize() )    {return false;    }

return true;}

// 引擎的相关内存的销毁工作void ShutdownEngine(){// 释放渲染系统    if (g_Render)    {        g_Render->Shutdown();        delete g_Render;        g_Render = NULL;    }

// 释放输入系统    if(g_InputSystem)    {        g_InputSystem->Shutdown();        delete g_InputSystem;        g_InputSystem = NULL;    }}

  

45. GameProject9+输入检测相关推荐

  1. Arduino 按键输入检测,消抖示例程序

    Arduino 按键输入检测,消抖示例程序 在按键未做输入信号检测的硬件时,避免不了需要对其进行消抖处理,消抖方法可以时硬件消抖或者软件消抖.物理消抖的办法有:在按键旁边并联一个电容的电路,来消抖或者 ...

  2. sse——6位密码输入检测

    //6位密码输入检测 //从键盘输入6位仅由数字0~9组成的密码.用户每输入一个密码并按回车键后,程序给出判断:如果是数字,则原样输出该数字,并提示用户目前已经输入了几位密码,同时继续输入下一位密码: ...

  3. 【野火启明_瑞萨RA6M5】按键输入检测

    文章目录 一.GPIO输入--按键输入检测 二.硬件设计 三.软件设计 下载验证 一.GPIO输入--按键输入检测 按键检测原理 按键机械触点断开.闭合时,由于触点的弹性作用,按键开关不会马上稳定接通 ...

  4. 输入检测的诡异问题--firefox和ie的兼容性

    最近被firefox和ie的兼容性搞的很不爽,因为以前没做过firefox下的东东,都是做出产品来,然后告诉客户说你必须用***浏览器,否则不支持....呵呵,现在客户是上帝了,必须考虑各种情况. 今 ...

  5. 编辑距离 在输入检测中的应用

    在office中输错了单词,office会在单词下方用红色波浪线标出来,你右击它,在菜单中会提示正确的单词拼法:在翻译词典中输入单词时拼错了某个字母,词典会智能的提示你可能想输入的单词. 其实这里用到 ...

  6. HAL库教程3:引脚输入检测

    使用CubeMX配置输入引脚   本章我们要把按键作为输入源,使用单片机来检测引脚的电平状态.首先要查看原理图,按键与那些引脚相连.   我使用的板子,按键K2 -K5分别对应PA4-PA7,且按键按 ...

  7. 开关量输入检测与输出的电路设计(转)

    问题由来: 两个板子之间要通过开关量通信,比如,我这个板子发现你那个板子是高电平,我就怎么样:我给你输出一个高电平,你那边的板子就怎么样.就是这么一个开关量通信的问题. 主要问题是:低电平肯定都是0, ...

  8. 汇编——十六进制输入转换十进制输出(附加输入检测)

    题目描述 输入一个最大长度为4的十六进制数,将其转换成10进制输出. 其中我们需要检测十六进制输入的正确性,比如大小写.特殊字符和数字的判断. 解决方式 程序分为两个部分,首先是处理我们的输入,以及通 ...

  9. python发送esc_Python组合键输入检测ESC和En

    在下面的doDebuggingMenu函数中,我使用raw_input函数(使用python2.6)获取用户输入.此函数将一直等到用户输入字符序列并按enter键.当然,我希望用户只需按键盘上的ESC ...

最新文章

  1. 一文为你详解2D与3D人脸识别有什么区别?
  2. 邮件服务器轻松组建 友旺MG1200功能介绍
  3. OpenNebula 入门安装配置
  4. 微信遇到特殊服务器,解决微信网页授权,出现errcode:40163,errmsg:codebeenused,看似微信访问了2次这个回调接口的问题...
  5. [HNOI 2015]接水果
  6. 安装Cornerstone3.1注意点
  7. CSS3 Media Query实现响应式Web设计(针对不同移动设备宽度)
  8. python最小二乘法求a b_python_numpy实用的最小二乘法理解
  9. mysql 联合主键_Mysql 创建联合主键
  10. 第十六章:SpringCloud Config 配置自动刷新
  11. 【网络流24题】No.4 魔术球问题 (二分+最小路径覆盖)
  12. 最全盘点:27类激光技术前沿应用
  13. linux查看历史命令history
  14. 为什么4G、5G又称为蜂窝网络?跟蜂窝有什么关系?
  15. 谷歌地球的高清卫星影像数据都来源自哪里?用户如何下载谷歌影像?
  16. rancher导入集群时证书报错
  17. js+高德地图api实现地理定位
  18. tcpdump manual 中文翻译
  19. 服务器显卡驱动安装NVIDIA-1080Ti
  20. 发明计算机的人的名人名言,60句关于发明的名言

热门文章

  1. 新浪微博瘫痪,有人开心有人哭
  2. 客户端JavaScript加密数据,服务端Java解密数据
  3. bug带来的兄弟感情
  4. 【Extjs】large按钮,图片全部覆盖按钮
  5. love2d--glsl03噪声
  6. python数据结构之二叉树的实现
  7. 25 iOS performance TipsTricks 笔记
  8. Silverlight 2.0 RTW 正式版发布(附下载地址)!
  9. javascript中的异步 macrotask 和 microtask 简介
  10. 20160531-20160607springmvc入门