掌握DirectX和DirectInput—力反馈游戏杆(1)

  不知不觉中,Windows下的游戏和多媒体程序已经开始流行。硬件变得越来越快,Windows也变得更加灵活。自从Microsoft发布了DirectX,游戏开发人员对其它平台已经越来越不感兴趣了。许多游戏开发者也已经将他们的开发工作完全移植到了Windows下。

     PC开发游戏从来就没有轻松过。从无数种显示卡和声卡中,开发者学会了在功能性和兼容性之间平衡的艺术。他们不得不处理象页面切换、段内存结构和位操作这样令人讨厌的问题。并且随着多人游戏的流行,开发者必须同时处理象网络和通信等事项。DirectX引入后,游戏开发者变得轻松了。通过为开发者提供的DirectX对象,绝大多数讨厌的工作已经被简化了。

     基于DirectX的程序是普通的Windows程序吗?必须懂得COM吗?为简单的程序值得使用DirectX吗?必须使用DirectX的全部组件吗?这样的问题肯定还有更多。

     本文将首先介绍DirectX,然后介绍DirectX的一个组件DirectInput的使用。演示程序说明了DirectInput的用法,着重介绍了其强大的反馈功能。

DirectX揭密

     DirectX是一套为Windows程序提供对系统硬件更亲密控制的组件。(表1列出了DirectX 5.0的组件及其作用)。那么,亲密控制是什么意思呢?

1DirectX 5.0的组件

组件

用途

DirectDraw

高速2D图象

DirectSound

短响应时间声音输出

Direct3D

高速3D图象

DirectInput

面向游戏的对游戏杆和其它输入设备的访问

DirectSetup

方便的安装DirectX组件

DirectPlay

面向游戏的通信和网络支持

DirectShow

视频流支持

DirectAnimation

动画录放支持

     DirectX提供的硬件控制常常被描述成底层控制,这会使人联想起位操作和其它讨厌的事情。实际上,DirectX组件包含许多高层API,使得象复制位图和播放声音等复杂的工作变得相当简单。用“为程序提供比过去更好的对硬件的控制”来形容DirectX更准确。这在Windows中是一个显著的特性,因为在Windows中,资源是共享的,并由操作系统控制。

     DirectX组件遵守称为COM的二进制对象的工业标准。

开始DirectX

     下面从DirectX的安装开始讲起。大多数情况下,某个好玩的游戏就会为系统安装DirectX。为得到最新的版本,应该从最新的Microsoft Platform SDK中将DirectX安装到系统中。可以在http://www.microsoft.com/msdn站点或者MSDN光盘中找到platform SDK。缺省情况下,Microsoft Platform SDK被安装到缺省驱动器根目录下的\MSSDK目录中。DirectX的头文件安装在\MSSDK\INCLUDE目录中,Lib文件安装在\MSSDK\LIB目录中。

     Platform SDK包含了一些非常好的DirectX例子和文档。早期发布的DirectX文档非常粗略而且有些是错误的,现在的版本已经极大地改正了这一问题。最好要熟悉这些文档。

     现在已经为安装利用DirectX的程序做好了准备。所幸的是,不必一次就处理DirectX的全部功能。DirectX是一套可以分别使用的组件。实际上,在编程概念中,DirectX的不同部分互相没有联系。它们仅仅是具有相同的设计风格和目标:使Windows的游戏编程变得容易。

     使用DirectX组件的程序有什么特殊的地方吗?根本没有。使用DirectX组件的程序是基于Win32的程序,它们使用普通Win32 API集,并且可以访问所有可以获得的操作系统工具。实际上,DirectX既可以用于GUI程序,也可以用于控制台程序。可以直接用Petzold-style SDK编程开发程序,也可以用基本类库,如MFC。总的说,唯一的要求是大多数DirectX组件在程序中需要HWND,所以至少要有一个窗口。

     虽然DirectX组件是分离的,但是每个组件的实现风格和使用都是相同的。DirectInput是学习DirectX的非常好的出发点,原因是DirectInput是最简单的组件之一。

用力

     以后在游戏中要“用力”,这是电影《星球大战》中的说法,因为DirectInput中加入了相当令人陶醉的力反馈支持。DirectX 5.0以前,DirectInput支持从鼠标和键盘读取输入,这是一个有用但却令人厌烦的特性。DirectX 5.0中,DirectInput被扩充到支持具有以物理力的形式向用户传播反馈的能力的设备。

     如果不能立即理解上面的内容,下面就用一个游戏进行解释。假设你刚启动了你最喜欢的超现实3D越野赛车游戏,正手握力反馈游戏杆。在起跑线上,你可以听到赛车引擎的空转声,同时也能够通过游戏杆感觉到赛车引擎的空转!比赛开始后,你可以感觉到引擎高速旋转的嗡嗡震动。当行驶到赛程中崎岖的地段时,你将会不停的感觉到电子碰撞。赛车在整个赛场上撞来撞去,你的游戏杆也会如此。赛车车轮卡在车辙中导致赛车被拉向左边,游戏杆也会被拉向左边!整个过程中你可以感觉到每次颠簸、刮擦、撞击和撞毁。

     现在,带有支持DirectInputWindows驱动程序的唯一的力反馈设备是MicrosoftSideWinder Force Feedback Pro。这一现状不会持续太久,新设备以及现有设备的新驱动程序很快就会进入市场。

剖析DirectInput

     DirectInput由三个对象组成:DirectInput, DirectInputDevice, DirectInputEffect (见表2)DirectInput是一个高层的对象,通过DirectInput对象可以对相关的输入设备进行基本的初始化和查找。DirectInput对象最终用来创建低层的DirectInputDevice对象。DirectX中的每个主要组件都采用相同的方法,首先创建高层对象,如DirectInputDirectSound对象,然后创建低层对象与硬件进行实际的通信。

2: DirectInput对象

对象

说明

DirectInput

封装高层DirectInput功能,列举设备并用来创建DirectInputDevice对象。

DirectInputDevice

与物理输入设备的接口,例如游戏杆,包括收集和设置设备状态信息的接口,并且用来创建DirectInputEffect对象 (对于力反馈设备)

DirectInputEffect

封装能够在力反馈设备上“播放”的简单效果,提供启动、停止和设置力反馈效果等功能。

     DirectInput对象是三个对象中最容易理解的。实际上,它在一个接口形式IDirectInput (见表3)中只提供五个函数。这是DirectInput的一个非常重要的部分,因为这是出发点。

3IdirectInput接口

成员函数

说明

CreateDevice

创建一个DirectInputDevice对象并返回一个指向其IdirectInputDevice接口的指针。

EnumDevices

为找到的与给定标准匹配的每个设备调用一个回调函数,每个回调函数提供一个GUID,可以用在CreateDevice中创建DirectInputDevice对象。

GetDeviceStatus

测试物理设备是否连接到系统。

Initialize

如果DirectInput对象是使用CoCreateInstance创建的,那么在使用前必须调用Initialize成员。如果DirectInput对象是使用DirectInputCreate创建的,那么就已经初始化过了。

RunControlPanel

为设备运行Windows Control Panel程序,让用户安装新设备或者更改已有设备的配置。游戏杆校准可以在此处做。

创建DirectInput对象

     为了创建DirectInput对象并得到其IdirectInput接口指针,应该在程序初始化阶段使用两种方法之一完成。

     第一种方法相当简单。DirectX提供了一个助手函数DirectInputCreate来创建并初始化DirectInput对象。它与所有DirectInput的函数、接口和宏定义都在头文件DINPUT.H中声明。实际的函数体在DINPUT.LIB文件中。

DirectInputCreate如下定义:

HRESULT WINAPI DirectInputCreate(

  HINSTANCE hinst, 

  DWORD dwVersion, 

  LPDIRECTINPUT * lplpDirectInput, 

  LPUNKNOWN punkOuter 

);


 

     第一个参数是应用程序的实例。第二个参数是程序需要的DirectInput版本,通常使用DIRECTINPUT_VERSION宏,定义为当前版本。第三个参数最重要,如果对COM非常陌生的化就很难理解,它是指向IdirectInput接口的指针的地址。程序中应该定义一个LPDIRECTINPUT类型的变量(可以是全局的)并将其地址作为第三个参数传递给DirectInputCreate

     最后一个参数叫作punkOuter,与COM技术中的聚合有关,可以用NULL安全的忽略。返回值是一个HRESULT,是COM的标准返回类型,可以将返回值与可能的返回值比较,也可以使用COM宏定义SUCCESSFAILED来检查。

     使用DirectInputCreate能够容易地创建高层对象并得到其主接口指针。这是DirectX的又一个设计方法,每个DirectX组件都提供助手函数来创建高层对象,例如DirectInputCreateDirectDrawCreate。在程序中可以用这些助手函数创建DirectX对象,然而,这些函数实际上创建的是COM对象。这个工作也可以用叫作CoCreateInstance的标准Win32 API函数来完成。这就引出了创建DirectInput对象的第二中方法。

     Win32中用CoCreateInstance创建COM对象非常普遍。如果程序中已经使用CoCreateInstance创建了其他COM对象,开发者可能就会希望也用它来创建DirectX对象。因为COM对象在安装时就在系统中注册过,所以唯一需要知道的就是对象的GUID,用它来创建一个实例。创建DirectX对象需要的全部GUID都在头文件中声明,并在库文件DXGUID.LIB中定义。可以将一个预定义的GUID传递给CoCreateInstance,让Windows为你创建对象。

CoCreateInstance定义如下:

STDAPI CoCreateInstance(

  REFCLSID rclsid, 

  LPUNKNOWN pUnkOuter, 

  DWORD dwClsContext, 

  REFIID riid,

  LPVOID * ppv

);

 

     第一个参数是要创建对象的GUIDDirectX定义的GUID是叫作CLSID_DirectInputGUID结构变量。第二个参数是熟悉的pUnkOuter,同样可以用NULL忽略。第三个参数dwClsContext定义COM对象在何处创建,DirectX只支持进程内服务器,所以必须使用CLSCTX_INPROC_SERVER

     第四个参数是两种方法真正的不同之处。记住COM对象对外提供接口,与对象本身一样,接口也用GUID识别。使用第一种方法,不能选择得到的接口,总是得到IdirectInput。使用CoCreateInstance可以请求对象所支持的任何接口,方法是使用为接口预定义的GUID。但是在DirectInput这是没有意义的,因为DirectInput对象的唯一有用的接口就是IdirectInput。其它DirectX组件支持多个有用的接口。(例如,DirectDraw对象可以用IdirectDrawIDirectDraw2接口操作。)

最后一个参数是程序中接口指针变量的实际地址。

现在就拥有了对象和对象的一个接口。CoCreateInstance方法还需要另外一步:必须要首先调用一个接口函数初始化对象。DirectInputCreate提供的是一个已经初始化过的DirectInput对象,但CoCreateInstance没有特定于DirectInput的认识,因此必须调用IdirectInput接口的初始化成员函数。假设如下定义IdirectInput接口指针变量:

LPDIRECTINPUT g_lpDI

     可以如下调用初始化函数:

g_lpDI->Initialize( hInstance, DIRECTINPUT_VERSION);

     既然选择采取这种标准方法创建对象,就不得不注意COM需要的其他标准,例如需要调用CoInitializeCoUninitialize

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值