编程基础 – 游戏杆输入_第1页
编程基础 – 游戏杆输入_第2页
编程基础 – 游戏杆输入_第3页
编程基础 – 游戏杆输入_第4页
编程基础 – 游戏杆输入_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、目 录3.1 为有效设备编写代码3.2 游戏杆轴3.3 游戏杆轴算法3.4 视点帽3.5 游戏杆按钮3.6 获取立即游戏杆数据DirectInput在DirectX 5.0以前版本中,除了提供某些嵌入Windows API的函数(类似于joyGetPosEx)外,没有给游戏杆提供别的服务。实际上,游戏杆在不久以前还只是输入设备家庭中一个可怜的成员,它除了一根杆和至多四个按钮以外一无所有,而且其中两个按钮似乎从不做任何工作,游戏杆在一些飞行模拟器中只起辅助作用,那里的一些基本功能如环顾四周或转舷等都必须靠键盘实现。但现在游戏杆已演变成一种具有多种功能的设备。配备有按钮、把手、滑块甚至引擎。同时,

2、其它的许多游戏控制器也已与游戏杆结合起来,包括游戏板、飞行轭、驾驶轮、踏板等。joyGetPosEx函数不能为这些设备提供足够的支持,但DirectInput以它对多达8条轴,128个按钮以及力反馈的支持做到了这一点。3.1、为有效设备编写代码PC的游戏控制器多种多样并且在不断变化,有些程序可能需要使用简单的两按键游戏杆,但如果提供有效减速控制,可视头盔及力反馈等,程序也能够利用它们。为适当地组织代码,程序员需要知道程序运行时有哪些设备与机器相连。 识别设备要寻找一种特定模型控制器,可以检测设备的DIDEVICEINSTANCE结构。可以在列举设备时得到这个结构也可以晚些时候调用IDDirec

3、tInput:GetDev9ceInFo方法。见表3-1。表3-1 GetDirectInfo方法HRESULT IDDirectInput:GetDeviceInfo( LPDIDEVICEINSTANCE pdidi); 参数说明LPDIDEVICEINSTANCE pdidiDIDEVICEINSTANCE结构地址信息结构见表3-2。 表3-2 DIDEVIEINSTANEC结构typedef struct DIDEVICEINSTANCE DWORD dwSize;GUID guidInstance;GUID guidProduct;DWORD dwDevType;TCHAR tszI

4、nstanceNameMAX_PATH;TCHAR tszProductNameMAX_PATH;GUID guidFFDriver;WORD wUsagePage;WORD wUsage;成员说明DWORD dwSize 结构的大小,调用DirectInput前初始化为Sizeof(DIDEVICEINSTANCE)GUID guidInstance此机器上此设备的独有标识,在会话之间保持不变GUID guidProduct此设备模型的独有标识DWORD dwDevType设备的类型和子类型如:DIDEVTYPE_JOYSTICK和DIDEVTYPEJOYSTICK_GAMEPAD使用GET

5、_DIDEVICE_TYPE和GET_DIDEVICE_SUBTYPE宏可以提取出这些值TCHAR tszInstanceNameMAX_PATH此实例在系统中是如何描述的,比如“Joystick 1”TCHAR tszProductNameMAX_PATH产品名如Microsoft Side WinderForce Feedback ProGUID guidFFDriver作用反馈使用的驱动器的独有标识WORD wUsagePage为HID支持而保留WORD wUsage为HID支持而保留寻找特定设备时,guidProduct是最有用的成员之一。在写代码前必须先从制造商或已知驱动器处获得此值

6、。如果想让用户能在有效设备中进行选择,则要在跟踪每个设备的guidInstance时创建一个“昵称”(可能会使用tszinstanceName和tszProductName)的列表。假设程序正是这样做的,它为options对话框列举所有设备,每当它向列表中添加设备时,它动态地保存实例的GUID,并把其地址作为列举项的数据而存储。当用户从列表中选出想要的输入设备后,其GUID将被取出并被用作DirectInput:CreateDevice的rguid参数。这里的小示例程序还缺少一种作为商业程序的基本特征:它并不把选定的实例GUID存到配置文件中,使得用户不可以在下次以缺省方式使用它。3.1.2

7、获取性能假设用户已选定了一种输入设备,但编程时不需考虑它是哪种特定类型,知道它是一种控制器或者甚至知道它是传统的游戏杆或游戏板就足够了,现在所需要的是找出它能做些什么,所用的工具见表3-3。表3-3 GetCapabilities方法HRESULT IdirectInputDevice:GetCapabilities(LPDIDEVCAPS lpDIDevCaps); 参数说明LPDIDEVICECAPS lpDIDevCapsDIDEVCAPS 结构的地址仅有的参数是指向表3-4中结构的指针。表3-4 DIDEVCAPS结构typedef struct DIDEVCAPS DWORD dwS

8、ize;DWORD dwFlags;DWORD dwDevType;DWORD dwAxes;DWORD dwButtons;DWORD dwPOVs;DWORD dwFFSamplePeriod;DWORD dwFFMinTimeResolution;DWORD dwFirmwareRevision;DWORD dwHardwareRevision;DWORD dwFFDriverVersion; 成员说明DWORD dwSize 结构的大小,必须被初始化为sizeof(DIDEVCAPS)DWORD dwFlagsDIDC_*标志的组合表明多种性能,如设备是否处于联接状态,是否支持作用反馈

9、,或是否含有需要轮询的对象DWORD dwDevType与DIDEVICEINSTANCE (表3-2)中的相同成员一样DWORD dwAxes轴的数目DWORD dwButtons按钮的数目DWORD dwPOVs可视头盔的数目DWORD dwFFSamplePeriod连续原始作用力命令回放的最短时间间隔DWORD dwFFMinTimeResolution力反馈时间单位DWORD dwFirmwareRevision版本号DWORD dwHardwareRevision版本号DWORD dwFFDriverVersion版本号当需要查询设备上轴、按钮或可视头盔的数目时会用到此结构,但如果

10、想检验设备上是否有特定的设备时,要调用DirectInputDevice:GetObjectInfo方法(表3-5)并使用该对象的标识值。如果返回DI_OK则表明对象存在;如果返回DIERR_OBJECTNOTFOUND则表示未找到。表3-5 GetObjectInfo方法HRESULT DirectInputDevice:GetObjectInfo( LPDIDEVICEOBJECTINSTANCE pdidoi,DWORD dwObj,DWORD dwHow);参数说明LPDIDEVICEOBJECTINSTANCE pdidoi DIDEVICEOBJECTINSTANCE结构地址,见第

11、23章列举设备物中对此结构的说明,不要在使用前初始化其中的dwSize成员DWORD dwObj对象的标识如DIJOFS_RZDWORD dwHow如果该对象以编移量标识,则此值为DIPH_BYOFFSET最后,当验证完特定按钮或轴是否存在以后,也许还想知道它的更多的性能,如它是否可用于触发力反馈效果或力是不是可以加到上面。这些信息都在刚获得的DIDEVICEOBJECTINSTANCE结构中。3.2、游戏杆轴前面已讲过,对鼠标而言,轴的模式天生就是相对的。也就是说,有关轴的数据是指上次检查后运动的距离,而不是到理论原点的距离。但对游戏杆而言却正好相反。程序更感兴趣的是轴的位置包括拨号盘,滑块

12、以及杆本身的侧向运动和扭曲而不是运动本身,因此对MicrosoftDirectInput而言,游戏杆轴的缺省模式为绝对轴。3.2.1 侧向轴对杆本身的侧向运动而言,轴的值与鼠标轴类似:X轴由左到右增加,Y轴由远及近增加, 对有Z轴的设备而言,Z轴值由高到低增加。 3.2.2 其它轴对于其它轴产生的一些混淆起因于人类接口设备HID标准的出现, 这是为新型通能串行总线USB开发的一个类(可在USB主页上得到有关这种标准的更多信息:滑块和拨号盘。传统游戏杆中,典型的滑块当向用户运动时其值增大。在HID标准中,滑块轴应从近及远地增大,拨号盘应沿顺时针方向增加。旋转轴。最普通的旋转轴是Rz轴或舵控制。典

13、型实现是杆的扭转动作,之所以称其为Rz轴是因为它绕上下轴旋转。Rx轴绕左右轴旋转, 有点象机车的减速杆,Ry轴绕前后轴旋转,象墙上的拨号盘。HID标准要求旋转轴遵守右手定则,即从侧向轴的负端看去旋转是顺时针方向的,(见图3-1)。这样,游戏杆的舵控制,从Z轴上方看去是顺时针的,当沿该方向扭动时,其值增大,Rx轴象机车的减速杆,当顶端向用户旋转时其值增大,但Ry轴与直觉有点不同,因为Y轴的负方向是在远离用户的一方,因此从用户的角度看时,Ry轴逆时针旋转其值增加。图 3-1 为人类接口设备定义的轴统3.3、游戏杆轴算法确定用户选定了所需的硬件并且已知道了设备上所需的多个按钮及把手的信息之后,只需再

14、越过一点障碍,就可以真正开始采集输入数据了。对鼠标而言,DirectInput可以简单地以驱动器提供的任何单位汇报轴的行动,但游戏杆要求必须指定如何将物理运动转换成数字。这里有一点值得注意,与鼠标和键盘不同,DirectInput中游戏杆要用到控制面板中的设置。因此,在将游戏杆应用到程序之前并不需要用户进行校准,但也可以在菜单中提供这一选项(以调用DirectInputDevice:RunControlPanel方法作为其响应)。只要游戏杆在控制面板中已校准,那么它在DirectInput中的表现也是可预计的。3.3.1 范围第2章中有一个DirectInputSetProperty的例子,用

15、于设置最小值为-1000最大值为1000的X轴范围。它的意义即是DirectInput把驱动器返回的数据进行缩放以适合这个范围,轴的中心就在你所期望的地方,在范围的正中。此例中,中心落在0点,但同样可以把范围改设为1000到10,000,把轴中心放在5500。选用什么方法进行设置并无太大关系。3.3.2 盲区只要已设置了范围,就可以对其进行限定,程序员或许希望游戏杆沿某一测向轴稍稍移动一点而不让游戏对此产生响应。不需要修改代码 比如要忽略小于偏离中心1000单位的值 可以让DirectInput代劳。这就要设置轴的盲区 需要用到的工具又是SetProperty。通过设置DIPH_DEVICE的

16、dwHow。可以立即为所有轴建立盲区。但由于这样也会影响所有的拨号盘、滑块和扭动杆,所以最好还是分别为X轴和Y轴进行调用,下面是为X轴进行的调用。DIPROPDWORD dipdw;dipdw.diph.dwSize= sizeof( dipdw );dipdw.diph.dwHeadrSize = sizeof( dipdw.diph );dipdw.diph.dwObj = DIJOFS_X;dipdw.diph.dwHow = DIPH_BYOFFSET;dipdw.dwData = 1000;if ( FAILED( g_lpdid2->SetProperty( DIPROP_D

17、EADZONE, &dipdw.diph ) ) )return FALSE;设置轴盲区的dwData值总在O到10,000之间,并不考虑对轴设置的范围。换句话说,它是百分比数值的100倍,上例中,设置的盲区是轴运动距离的10%。当然,盲区的一半在中心位置的一侧,一半在另一侧。设置盲区不会截短已设的范围,盲区被压缩到轴物理范围的更小的区域中。上例中,当杆超出盲区时DirectInput汇报±1值,在余下的物理范围内,使用完全范围宽度的值。3.3.3 饱合度饱合度和盲区很相似,但它位于轴的两端而不是中间,饱合区里是一种补偿杆在不同位置得到极值的微小差异的有效方法,例如,X轴最大

18、值可能因其在右上角,正右方,右下角而有所不同。上例中,如果不设饱合区,则DirectInput将只在驱动器返回最大原始值时才返1000。设置饱合度与设盲区很类似:DIPROPDWORD dipdw;dipdw.diph.dwSize= sizeof( dipdw );dipdw.diph.dwHeadrSize = sizeof( dipdw.diph );dipdw.diph.dwObj = DIJOFS_X;dipdw.diph.dwHow = DIPH_BYOFFSET;dipdw.dwData = 1000;if ( FAILED( g_lpdid2->SetProperty(

19、DIPROP_SATURATION, &dipdw.diph ) ) )return FALSE;这样X轴每一端的饱合区就是物理的移动范围的10%了,与盲区一样,返回值的范围不会被截短,在X轴正向,正好进入饱合区前DirectInput返回999,而在饱合区中的任何地方都返回1000。当然,盲区与饱合度之和不能超过9999,否则将占了整个轴。3.3.4 有关游戏板的一点说明游戏板上的定向轴与常规游戏杆中的工作起来略有不同,因为前者只能拥有中心位置和极值。如果只关心轴的方向,则为常规游戏杆编写的代码也可以很好地用到游戏板上。如果确实要关注轴的位置(比如想用为控制杆使之成为飞行控制器),但

20、同时还想支持游戏板,则必须给用户提供一些更好的途径,对轴进行很好地调整的其它方法。3.4、视点帽视点控制器,由于其通常位于游戏标的顶部而被称为帽,它既不是按钮也不是轴。与按钮不同,它有多于两种的状态;与轴也不同,它有固定的范围,不能使用盲区和饱合度。视点帽数据中含有其极坐标形式的位置,以从北方看或向前看去的方向开始的角度100倍来度量,当视点帽居中时,返回的位置依驱动器不同为OXFFFFFFFF或OXOOO0FFFF。要想从dwPOV值判断视点帽是否居中,可这样做:BOOL POVCentered = ( LOWORD( dwPOV ) = 0xFFFF;大多数视点帽度量间隔,为45或90度,

21、可以通过以DIPROP_GRANULARITY作为第一个参数调用IDirectInputDevice:GetProperty来获取此值。但通常还需要对驱动器返回的值做一些小小的修正。如SideWinder游戏杆,尽管它除中心POV位置外还有8个POV位置,但它返回的值以90为间隔。3.5、游戏杆按钮游戏杆按钮返回数据的方式与鼠标按钮或键盘键完全一样,如果按钮处于按下状态(立即数据)或被按下(缓冲区数据),则按钮返回的数据中DWORD的OX8O位为1。3.6、获取立即游戏杆数据大多数情况下,程序员感兴趣的是游戏杆轴的当前状态而不是每个运动的动作,所以现在详细讲述获取立即数据。回想一下设置设备时经过的一个步骤;设置数据格式。对DirectInputDevice:SetDataFormat的调用完成两种功能:使用按钮和轴的数据格式中的偏移量生成一个按钮和轴的识别系统;告知DirectInput立即数据使用什么样的结构。对游戏杆而言,此结构为DIJOYSTATE或DIJOYSTATE2这取决于传给SetDataFormat的是c_dfDIJoystick还是c_dfDIJoystick2。下面看一下DIJOYSTATE结构,见表3-6。除了非常复杂的游戏控制器,它几乎能全部适用。表3-6

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论