将DirectInput封装为基本的输入系统

DirectInput封装为基本的输入系统

作者:蒋轶民 创作于2011281:07:15

了解DirectInput的即时数据和缓冲数据后,我们开始着手制作一个简单的基于DirectInput的输入系统了。

我制作这样一个系统的思路是这样的:将那些琐碎的步骤全都封装在我自己写的一个类CInputSystem中。这个类是基于DirectX库的,主要提供键盘的处理。通过这个类,我们可以简单地控制键盘,并且提供了即时数据和缓冲数据。

对于错误处理,我并没有使用c++try-catch异常处理机制,而是使用了错误码。错误码对于简单的系统来说应该是很有效的,虽然在自己游戏的进程中可能会引起一些小麻烦,但是在最初的实验还是挺管用的,以后我还会修正充实。

在最初,我设计了这样的一个类:添加简单的默认构造函数和析构函数,然后制作了一个Initialize()函数,初始化了各项数据。这样就封装了细节,大大简化了我们的操作。另外我还提供了更新系统UpdateSystem()函数和检测按键按下的KeyDown()函数。另外我还提供了转化输入种类的ShiftInputStyle()函数。将DirectInput封装为基本的输入系统

UpdateSystem()函数和KeyDown()函数声明为内联函数,可以提升程序的运行效率。

下面就是我的InputSystem.h文件:

/*--------------------------------------------------------------------------- 蒋轶民制作 E-mail:[email protected] 文件名:InputSystem.h 作用:输入系统的头文件 ----------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/ // 条件编译 #ifndef _INPUTSYSTEM_H_ #define _INPUTSYSTEM_H_ // 定义的宏 #define DIRECTINPUT_VERSION 0x0800 // 使用DirectInput前需要确定DirectInput版本 // 头文件 #include <dinput.h> // 库文件 // 注意:所有库文件可以放在一块儿,也可以放在不同的地方。放在一块儿便于管理, // 放在不同的地方可以减小不同文件的耦合度。 #pragma comment( lib, "dinput8.lib") #pragma comment( lib, "dxguid.lib") /*--------------------------------------------------------------------------*/ // 枚举输入的种类 enum INPUTSTYLE { IMMEDIATE, BUFFERED }; enum RESULT_INPUT { OK_INPUT, // 无错误 ERR_INVALIDSYSTEM, // 无效的系统 ERR_OBJECTCREATE, // 创建对象错误 ERR_DEVICECREATE, // 创建装置错误 ERR_DATAFORMAT, // 创建数据格式错误 ERR_COOPERATIVELEVEL, // 创建合作等级错误 ERR_PROPERTY, // 设置缓冲数据错误 ERR_ACQUIRE, // 取得装置错误 ERR_UPDATE // 更新系统错误 }; /*--------------------------------------------------------------------------*/ // 定义的输入系统类 class CInputSystem { public: CInputSystem(): m_pInputObject( 0 ), m_pInputDevice( 0 ){}// 默认构造函数 ~CInputSystem(){}// 默认析构函数 RESULT_INPUT Initialize( INPUTSTYLE inputStyle, HINSTANCE hInst, HWND hWnd );// 初始化输入系统 inline RESULT_INPUT UpdateSystem( void );// 更新系统 inline int KeyDown( int key );// 检测按键是否按下 RESULT_INPUT ShiftInputStyle( INPUTSTYLE inputStyle );// 转换输入的种类 void Release( void );// 释放内存空间 private: LPDIRECTINPUT8 m_pInputObject;// DirectInput8的对象 LPDIRECTINPUTDEVICE8 m_pInputDevice;// DirectInput8的设备 public: INPUTSTYLE m_InputStyle;// 输入的种类 DIDEVICEOBJECTDATA m_DeviceObjData;// 缓冲数据用的设备对象数据 char m_KeyState[256];// 即时数据用的键盘映射的字符 }; typedef CInputSystem* LPCInputSystem; /*--------------------------------------------------------------------------*/ // 检测按键是否按下 inline int CInputSystem::KeyDown( int key ) { return m_InputStyle == IMMEDIATE? m_KeyState[key] & 0x80: m_DeviceObjData.dwOfs == key; } /*--------------------------------------------------------------------------*/ // 更新系统 inline RESULT_INPUT CInputSystem::UpdateSystem( void ) { HRESULT hr; // 判断输入种类再更新 if ( m_InputStyle == IMMEDIATE ) hr = m_pInputDevice->GetDeviceState( sizeof( m_KeyState ), m_KeyState ); else { m_DeviceObjData.dwOfs = 255;// 重新设置设备对象数据,清除缓冲 DWORD dwItems = 8; hr = m_pInputDevice->GetDeviceData( sizeof( DIDEVICEOBJECTDATA ), &m_DeviceObjData, &dwItems, 0 ); } // 如果对输入设备失去控制,则重新获取输入设备,否则为其它错误。 if ( FAILED( hr ) ) { if ( FAILED( m_pInputDevice->Acquire() ) ) return ERR_UPDATE; } return OK_INPUT; } /*--------------------------------------------------------------------------*/ #endif

我们这样调用:

将DirectInput封装为基本的输入系统

通过测试,成功,并且效果不错。以下就是我的截图,通过按下B键可以转换为缓冲数据,按下I键可以转换为即时数据。缓冲数据和即时数据的差别是很大的,我们可以通过截图来证实。

将DirectInput封装为基本的输入系统

好啦,把基本输入系统做好了,接下来就可以进行我的数据存储和读取系统了,这是我上个学期落下的工程,现在一定要完成!

源代码和说明文档请点这里->http://download.****.net/source/3016618