directinput中怎么让2个iphone游戏手柄柄同时工作,100-CSDN论坛

&>&利用directinput 进行手柄编程 例程 VC++
利用directinput 进行手柄编程 例程 VC++
上传大小:2.86MB
此资源是本人下载directx SDK中的examples自带的,压缩包中上传了最终的可执行,调试成功。
是非常好的利用directinput进行手柄开发的C++例程,望能对各位有所帮助。
综合评分:4(28位用户评分)
所需积分/C币:
下载个数:177
{%username%}回复{%com_username%}{%time%}\
/*点击出现回复框*/
$(".respond_btn").on("click", function (e) {
$(this).parents(".rightLi").children(".respond_box").show();
e.stopPropagation();
$(".cancel_res").on("click", function (e) {
$(this).parents(".res_b").siblings(".res_area").val("");
$(this).parents(".respond_box").hide();
e.stopPropagation();
/*删除评论*/
$(".del_comment_c").on("click", function (e) {
var id = $(e.target).attr("id");
$.getJSON('/index.php/comment/do_invalid/' + id,
function (data) {
if (data.succ == 1) {
$(e.target).parents(".conLi").remove();
alert(data.msg);
$(".res_btn").click(function (e) {
var q = $("#form1").serializeArray();
console.log(q);
var res_area_r = $.trim($(".res_area_r").val());
if (res_area_r == '') {
$(".res_text").css({color: "red"});
$.post("/index.php/comment/do_comment_reply/", q,
function (data) {
if (data.succ == 1) {
var $target,
evt = e || window.
$target = $(evt.target || evt.srcElement);
var $dd = $target.parents('dd');
var $wrapReply = $dd.find('.respond_box');
console.log($wrapReply);
var mess = $(".res_area_r").val();
var str = str.replace(/{%header%}/g, data.header)
.replace(/{%href%}/g, 'http://' + window.location.host + '/user/' + data.username)
.replace(/{%username%}/g, data.username)
.replace(/{%com_username%}/g, _username)
.replace(/{%time%}/g, data.time)
.replace(/{%id%}/g, data.id)
.replace(/{%mess%}/g, mess);
$dd.after(str);
$(".respond_box").hide();
$(".res_area_r").val("");
$(".res_area").val("");
$wrapReply.hide();
alert(data.msg);
}, "json");
/*删除回复*/
$(".rightLi").on("click",'.del_comment_r', function (e) {
var id = $(e.target).attr("id");
$.getJSON('/index.php/comment/do_comment_del/' + id,
function (data) {
if (data.succ == 1) {
$(e.target).parent().parent().parent().parent().parent().remove();
$(e.target).parents('.res_list').remove()
alert(data.msg);
//填充回复
function KeyP(v) {
$(".res_area_r").val($.trim($(".res_area").val()));
评论共有18条
好用,谢谢分享
毕竟免费, 还不错
Sdk 自带资源还要这么多积分!例子不完整,缺少 部分头文件和lib文件!
绝对满分!非常给力啊!所有的按钮都有对应的响应!程序包好像有缺失,一个是图标,一个是库文件dxguid.lib
代码可以参考。
vs2010可以,但是要下载库
代码可以参考,库得自己去下
懂得包里面有什么,其实剩下就简单了……
代码值得参考,正在研究directinput中的手柄控制,想用它控制方向盘
还不错,顺便可以学习C++,Vs2010可以通过
审核通过送C币
Visual Assist 10.9.22xx
创建者:shuren8
opencv3基础入门
创建者:xyz59886
C++经典书籍
创建者:revofu
上传者其他资源上传者专辑
Java培训课程PPT
solidworks 两级圆柱齿轮减速器三维图
两级圆柱齿轮减速器solidworks建模
数控技术综述
开发技术热门标签
VIP会员动态
下载频道积分规则调整V1710.18
CSDN下载频道积分调整公告V1710.17
开通VIP,海量IT资源任性下载
spring mvc+mybatis+mysql+maven+bootstrap 整合实现增删查改简单实例.zip
CSDN&VIP年卡&4000万程序员的必选
为了良好体验,不建议使用迅雷下载
利用directinput 进行手柄编程 例程 VC++
会员到期时间:
剩余下载个数:
剩余C币:200
剩余积分:6726
为了良好体验,不建议使用迅雷下载
积分不足!
资源所需积分/C币
当前拥有积分
您可以选择
程序员的必选
绿色安全资源
资源所需积分/C币
当前拥有积分
当前拥有C币
(仅够下载10个资源)
全站1200个资源免积分下载
为了良好体验,不建议使用迅雷下载
资源所需积分/C币
当前拥有积分
当前拥有C币
全站1200个资源免积分下载
资源所需积分/C币
当前拥有积分
当前拥有C币
您的积分不足,将扣除 10 C币
全站1200个资源免积分下载
为了良好体验,不建议使用迅雷下载
你当前的下载分为234。
你还不是VIP会员
开通VIP会员权限,免积分下载
你下载资源过于频繁,请输入验证码
你下载资源过于频繁,请输入验证码
您因违反CSDN下载频道规则而被锁定帐户,如有疑问,请联络:!
若举报审核通过,可奖励20下载分
被举报人:
melody2008
举报的资源分:
请选择类型
资源无法下载
资源无法使用
标题与实际内容不符
含有危害国家安全内容
含有反动色情等内容
含广告内容
版权问题,侵犯个人或公司的版权
*详细原因:
利用directinput 进行手柄编程 例程 VC++22:06 提问
C#利用directinput模拟joystick数据
打算写个小程序,利用手机加速度感应器获得手机与实际世界坐标的角度来模拟赛车游戏(比如nfs)的方向盘手柄,手机端做好了,电脑网络传输接收端也做好了,但是找不到好办法来模拟手柄的输入,网上好像说可以用Windows的directinput来模拟,但是找到的资料全都是接收手柄信息作处理的(与我这个程序的目的可以说正好相反),找了好几天资料都没找到比较好的解决办法,所以来csdn请教各位大大了。
(其实c/c++,java,c#我都能写,只要能解决都好说)
按赞数排序
你好,我也在找同样的东西,之前研究过windows.joystick API里面没有的,现在把希望都寄托在directinput了。。。
其他相关推荐创作背景:近期,一友人希望使用手柄代替键盘玩格斗游戏,自行写了款手柄键盘模拟器,结果在游戏时无法正常运行,托在下看看。程序写得不错,手柄很准确地在记事本上输出键盘键码。
然而,进入游戏,却什么反应都没有。一个念头闪现出来,游戏的输入是通过directinput实现的,比WINDOWS API 更接近底层,这样可以赢取更短的响应时间,程序需向directinput改进,然而这里不得不说下:上网搜索大小网站都是那篇API 实现手柄信息获取的文章,和友人的代码90%的相似度,文章写得很好说真的,但全是这篇就有点过了。国内没有要找的就找下国外吧,百度的确有些害人,因为太懂中文,国外的directinput一张都没有,立马换了搜索页,2小时就用directinput完成了手柄信息获取,然而殊不知接下来的震动功能花费了4天时间…
完成后界面:
功能目标: 1、获取手柄方向、按键信息;2、使手柄震动
&&&&&&&&&&&&&&& 注意,本程序只是通过DX发送震动信息,并不是什么万能手柄驱动啊。
&&&&&&&&&&&&&& &测试手柄震动前,请确认使用的是震动手柄并安装了手柄驱动。
开发环境:Win7 (DX10传说中的DX11类库我没有找到,结果项目建了.NET 3.5)
&&&&&&&&&&&&&&&&&&&Microsoft Visual Studio 2010
&&&&&&&&&&&&&&&&&& & 数据库无
&&&&&&&&&&&&&&&&&& &代码在1920 X 1080 分辨率下无过长换行
&&&&&&&&&&&&&&&&&& &编写人数 1人
参考资料:
&&&&&&& 言归正传,在.NET的高封装的环境下,directinput的使用简化了许多,不了解COM的朋友,甚至是不知道句柄、指针的新手也可以轻易掌握。
思路与实现:首先,我们要计算机找到我们的摇杆设备
foreach (DeviceInstance info in Manager.GetDevices(DeviceClass.GameControl, EnumDevicesFlags.AttachedOnly))
Device myJoy = new Device(info.InstanceGuid);
&&&&&&& 然后控制设备,过去用c++的朋友很熟悉了,申请操作级别,这个真的很重要,在最后测试震动报了“没有独占打开无法操作”的异常,单步了整整一天,才发现是这里设错参了。
myJoy.SetCooperativeLevel(null, CooperativeLevelFlags.Background | CooperativeLevelFlags.Exclusive);
再设置其他参数
myJoy.Properties.AxisModeAbsolute =
myJoy.Properties.AutoCenter =
myJoy.Acquire();
int[] axis =
foreach (DeviceObjectInstance doi in myJoy.Objects)
if ((doi.ObjectId & (int)DeviceObjectTypeFlags.Axis) != 0)
myJoy.Properties.SetRange(ParameterHow.ById, doi.ObjectId, new InputRange(-128, 128));
&&&&&&&好了,目标1完成,很快是不?手柄的状态已经在myJoy. CurrentJoystickState下了,通过
myJoy. CurrentJoystickState. ToString() 你可以查看到摇杆状态(微软大费苦心啊,左摇杆、右摇杆、光枪,压杆,基本上能想到的有位移的操作杆都有了)
allJoystick.Joysticks[i].CurrentJoystickState.GetButtons()可以得到按下按钮组合的数组
&&&&&&& 好,开始进军震动了。震动不同于按键捕捉、不同于模拟键盘、鼠标击键,因为这些计算机都是作为信息的接受方,然而这次是手柄作为接受方。也与一些挂起、响应的程序不同,挂起的程序用于监听端口,当有数据流后运算后反馈硬件。
&&&&&&& 例如,我进入一款格斗游戏后不对手柄进行任何输入,时间到后自动选人开打,在被CPU攻击时手柄是有震感的。
也就是说震动指令是由计算机发起的,当时还真想用汇编给它来一段,装了个Bus Hound 5.0 抓包结果Win7蓝屏 花了1个多小时恢复。
&&&&&&& 扯远了,手柄的震动是像声音一样播放的,看参考资料,资料中例举了使用SDK下的录制好的震动文件来驱动,国外一达人说该函数有BUG,刚好我又不想下载几百兆的SDK。故选择了最后一种方式,现场定制(录制)、现场播放。
代码不难,调试却很罗嗦。
//震动类型
public enum ForceType
VeryBriefJolt,
BriefJolt,
LowRumble,
HardRumble
//录制函数,照抄参考资料
public static EffectObject InitializeForce(Device Dev, EffectType Type, int[] Axis, int Magnitude, EffectFlags Flags, int Duration)
EffectObject eo =
foreach (EffectInformation ei in Dev.GetEffects(EffectType.All))
if (DInputHelper.GetTypeCode(ei.EffectType) == (int)Type)
e = new Effect();
e.SetDirection(new int[Axis.Length]);
e.SetAxes(new int[1]);
e.EffectType = T
e.ConditionStruct = new Condition[Axis.Length];
e.Duration = D
e.Gain = 10000;
e.Constant = new ConstantForce();
e.Constant.Magnitude = M
e.SamplePeriod = 0;
e.TriggerButton = (int)Microsoft.DirectX.DirectInput.Button.NoT
e.TriggerRepeatInterval = (int)DI.I
e.Flags = F
e.UsesEnvelope =
eo = new EffectObject(ei.EffectGuid, e, Dev);
InitializeForce(myJoy, EffectType.ConstantForce, axis, 10000, EffectFlags.ObjectOffsets | EffectFlags.Spherical, 2000000).start(1);
&&&&&&& 用震动来按摩还真不错,附上调试好的源码,与各位同僚共勉:
本文已收录于以下专栏:
相关文章推荐
学了绘制简单的2D图形以及3D物体之后,该学学怎么控制物体了!
之前一直是用的是Windows自带的消息循环,WM_KEYDOWN,WM_MOUSELBUTTONDOWN等等,但是这个慢的不行,完全...
版本:VS2015 语言:C++
书的第八章是一些数学的知识,以及一个图形库的创建。数学知识是有必要看一看的,我这里就不做多的介绍了,图形库的话反正你现在的win7+系统上也运行不了,看看就好...
package com.example.
import android.content.C
import android.graphics.Bitm...
本系列文章由zhmxy555(毛星云)编写,转载请注明出处。  文章链接: http://blog.csdn.net/zhmxy555/article/details/8547531作者:毛星云(浅墨...
他的最新文章
讲师:汪剑
讲师:刘道宽
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)使用DirectInput对象
&&&& 一旦拥有了DirectInput对象,就可以用它来创建DirectInputDevice对象,来管理系统中特定的设备。创建DirectInputDevice对象要使用CreateDevice函数,它是作为IdirectInput接口一部分的五个函数之一。CreateDevice需要所请求设备的GUID,返回新DirectInputDevice对象的IdirectInputDevice接口指针。
HRESULT CreateDevice(
REFGUID rguid,
LPDIRECTINPUTDEVICE *lplpDirectInputDevice,
LPUNKNOWN pUnkOuter
&&&& 这些内容看起来很熟悉,因为它与CoCreateInstance和DirectInputCreate类似。但是,现在还没有完全准备好开始DirectInputDevice对象,原因是在创建DirectInputDevice对象前需要该设备的GUID。
&&&& DirectInput库为创建DirectInputDevice对象预定义了两个GUID:GUID_SysKeyboard和GUID_SysMouse。将两者之一直接传递给CreateDevice函数,就会得到相应设备的DirectInputDevice对象。
&&&& 注意,令人感到奇怪的是缺少对游戏杆的预定义GUID。在Windows中,通常都有系统键盘和系统鼠标,另一方面,系统本身并不使用游戏杆。可以安装一个或者多个游戏杆,但系统管理的范围只限于驱动程序级。系统并为这些设备指定特殊的系统状态,也不会在日常事务中使用这些设备。因此,为游戏杆定义GUID对DirectInput来说是不合理的。
&&&& 那么,如何才能找到与系统连接的游戏杆的GUID呢?要得到它们,必须要列举设备。列举系统设备和性能在DirectX中相当普遍。要列举系统中的输入设备,需要使用EnumDevices函数。EnumDevices是IdirectInput接口的一部分,如下定义:
HRESULT EnumDevices(
DWORD dwDevType,
LPDIENUMCALLBACK lpCallback,
LPVOID pvRef,
DWORD dwFlags
&&&& 注意此函数与Windows中其它列举API相同,例如EnumWindows。第二个参数是一个回调函数。第三个参数是程序中定义的32位值。第一个参数是想要列举的设备类型,对游戏杆来说,是DIDEVTYPE_JOYSTICK(全部的设备类型列在表4中)。最后一个参数是详细描述想要列举的设备的标志。现在支持的标志是DIEDFL_ATTACHEDONLY和DIEDFL_ALLDEVICES(这两个标志是互斥独占的),此外还有DIEDFL_FORCEFEEDBACK,此标志表示力反馈设备,能够和另两个标志位或操作。
图4:定义列举的输入设备
&&&& 以下定义的值可以传递给EnumDevices来选择列举哪种类型的输入设备。另外也支持子类型,见SDK中DIDEVICEINSTANCE结构的文档。
DIDEVTYPE_MOUSE
列举鼠标设备 (标准、轨迹球等)
DIDEVTYPE_KEYBOARD
列举键盘设备 (标准、键区等)
DIDEVTYPE_JOYSTICK
列举游戏杆设备 (操纵杆、操纵轮、方向舵等)
DIDEVTYPE_DEVICE
列举其它设备
&&&& 当EnumDevices列举系统中的输入设备时,反复地调用回调函数。回调函数定义如下:
BOOL CALLBACK EnumProc(LPCDIDEVICEINSTANCE lpddi,LPVOID pvRef) ;
&&&& 因为回调函数是由用户程序定义并传递给EnumDevices的,所以是调用CreateDevice的最合适地方,直到创建了满足需要的足够DirectInputDevice对象为止。但是回调函数并非一定要如此实现,可以简单的将列举设备的所有GUID保存在一个表中,在以后的代码中使用。
&&&& 回调函数接受两个参数。第二个参数是程序定义的传递给EnumDevices的32位值。更重要的是,第一个参数传递指向一个结构的指针,该结构包含关于能够与列举标准匹配的单个设备的许多信息。这是一个DIDEVICEINSTANCE结构。此结构中最重要的一条信息是设备的GUID,保存在结构的guidInstance成员中。
&&&& 当程序中完全完成DirectInput有关的工作后,就应该调用IdirectInput接口的Release成员。这就告诉DirectInput对象可以释放自己了。在DirectX中,最好养成释放对象的习惯,从低层对象开始,到高层对象结束。正常情况下程序会作为清除或者关闭的例行公事的一部分调用Release。这是使用每个DirectX组件的必要步骤,也是使用每个COM组件的必要步骤。
&&&& 现在已经用CreateDevice成员函数获得了DirectInputDevice对象的一个接口,为开始处理与系统连接的实际物理设备做好了准备。
使用DirectInputDevice对象
&&&& DirectInputDevice对象的每个实例都与系统中的特定设备相关。此对象提供了对系统硬件更多的控制和能力,从而使DirectX的允诺实现。下面讨论拥有了DirectInputDevice对象后下一步干什么。
&&&& 拥有了IdirectInputDevice接口的一个接口指针,现在干什么?首先,设置设备的数据格式。通过调用SetDataFormat来完成,该函数是一个接口成员函数。设置数据格式包括无数可能的决定,包括轴信息、相对或绝对坐标信息、等等。所有这些细节通过一个叫作DIDATAFORMAT的结构传递给此函数。实际上,SetDataFormat唯一的参数就是指向此结构的指针。
&&&& 填写这个结构的细节会使人发憷。值得感谢的是这一工作并不是必须的,因为DirectInput已经定义了几个DIDATAFORMAT结构变量,可以用于比较普通的输入设备:c_dfDIKeyboard, c_dfDIMouse, c_dfDIJoystick,
和c_dfDIJoystick2。为普通的力反馈游戏杆设置数据格式,可以使用下面的调用形式:
lpdid-&SetDataFormat( &c_dfDIJoystick ) ;
&&&& 在此例中,lpdid是指向IdirectInputDevice接口的指针。
&&&& 设置完设备对象的数据格式后,就需要设置设备的协作级别。因为协作级别在整个DirectX中很常见,所以这里要做一下说明。大多数直接处理系统硬件的DirectX对象在接口的成员中都有一个叫作SetCooperativeLevel函数。这个函数很重要,因为它定义了程序操纵与系统中其它进程有关的硬件的控制级别。同其它DirectX对象一样,只有设置了协作级别才能使DirectInputDevice对象工作。要理解协作级别,就需要熟悉Acquire函数。调用此函数是为了获得对物理设备的实际访问(不要和逻辑上的DirectInputDevice对象混了)。相反的,Unacquire函数释放对物理设备的访问。
&&&& 下面是函数SetCooperativeLevel的定义:
HRESULT SetCooperativeLevel(
HWND hwnd,
DWORD dwFlags
&&&& hwnd是程序的主窗口。标志是下面一些值的或操作的结合: DISCL_BACKGROUND, DISCL_FOREGROUND, DISCL_EXCLUSIVE, DISCL_ NONEXCLUSIVE。
&&&& 如果标志参数中或上了DISCL_EXCLUSIVE,则当获得设备后本程序就成为唯一允许访问该物理设备的进程。另一方面,如果选择了DISCL_NONEXCLUSIVE,那么系统中可以有多个进程同时协作获得和使用该设备。如果或上了DISCL_BACKGROUND,程序将不会失去物理设备。然而,象Ctrl+Alt+Del组合键被按下这样的系统事件仍然能够隐含地“unacquire”程序中的设备。如果使用了DISCL_
FOREGROUND,当不是活动窗口时,程序将会自动释放物理设备。这就是将程序主窗口句柄传递给SetCooperativeLevel的意义。DirectX根据窗口是否是系统当前活动窗口自动调整设备共享。
&&&& 那么所有这些值的意义是什么呢?下面举个例子说明。如果力反馈游戏杆的协作模式是DISCL_FOREGROUND | DISCL_EXCLUSIVE,那么只要程序处于活动状态,就能够从游戏杆读数据并播放力反馈效果(力反馈需要exclusive-level协作)。只要用户一选择其它程序,程序就失去对物理设备的控制,新激活的程序就能够访问该设备。这意味着在调试程序时,如果切换到调试器窗口,程序就会因为窗口变为非活动的而失去对游戏杆的控制。
&&&& 如果将同一游戏杆的协作级别设为DISCL_BACKGROUND | DISCL_EXCLUSIVE将会是什么情况呢?程序将会所有时间都能访问游戏杆,不管窗口的状态。但是现在系统中其它进程就不能获得游戏杆,除非程序释放了游戏杆,不管用户在做什么!
&&& 非常明显,在正式发布的产品中应该使用DISCL_FOREGROUND | DISCL_EXCLUSIVE,而在调试版本中应该使用DISCL_BACKGROUND|DISCL_EXCLUSIVE。但是也不总是这样选择。例如,如果设备是系统键盘,那么DirectInputDevice想独占使用而调用SetCooperativeLevel将会失败。这是因为操作系统想要允许用户自由地从一个程序切换到另一个程序。类似的,DirectInputDevice不会允许以协作级别DISCL_BACKGROUND|DISCL_EXCLUSIVE请求系统鼠标。Windows不希望一个程序能够完全将用户与操作系统的联系切断。
&&&& 在能够从物理设备读取信息或向物理设备发送信息之前,必须要用Acquire获得设备。在临时或永久结束设备使用时要明确地使用Unacquire函数释放设备。但Unacquire并不是失去设备控制的唯一方法。
&&&& 如果设置协作级别时使用DISCL_FOREGROUND标志,那么程序的主窗口不再是系统中的活动窗口时设备将被明确释放。这就是说,在程序调用Acquire和实际试图从设备读取信息之间,能够失去对设备的占有。所以需要检查返回值来捕捉这样的错误,并准备好在任何时间重新获得该设备。
&&&& 关于Acquire和Unacquire的决定性要点:当程序获得独占协作级别的设备时,DirectX拥有该设备。例如,如果鼠标被DirectX(独占)获得,那么程序窗口中的按钮就不会对鼠标做出响应。这就是说,如果想让Windows对设备响应,就应该释放该设备。换句话说,如果不想让DirectInput从设备中读取数据,就调用Unacquire。
&&&& 设置完设备的协作级别后,接着应该为设备配置其它设置。获得了设备后,接着就应该开始使用GetDeviceState函数轮流检测输入的数据。当完成与设备对象的操作后,调用Unacquire释放DirectInputDevice对象。设备与设备之间存在细节上的差别;下面讲解游戏杆和键盘,应该能为从其它设备读取输入提供足够的基础知识。
&&&& 键盘是到目前为止最容易读取的设备。实际上,设置完数据格式、协作级别、获得设备以后,就可以读取键盘状态了。读取键盘状态要使用IdirectInputDevice接口的GetDeviceState成员。GetDeviceState用关于物理设备的状态信息组装一个结构,所组装结构的类型由前面对SetDataFormat的调用决定。对键盘来说,此数据结构是一个简单的256个字节组成的数组。每个字节对应于键盘上的一个键,如果某个键按下,相应字节的高位就被设置。
&&&& DirectInput定义了一套以DIK_XXX为前缀的常量,这些常量可以用来索引字节数组以找到关于特定键的数据。例如,如果要检查右Shif键当前是否按下,可以使用DIK_RSHIFT定义:
GetDeviceState(256,(LPVOID) cKeyboardData) ;
if(cKeyboardData[DIK_ RSHIFT]&0x80)
DoWhatever() ;
&&&& CKeyboardData是256个字节的缓冲区。几乎就是这么简单,但是要记住,不管GetDeviceState在何时返回DIERR_INPUTLOST,就必须使用Acquire获得设备。这种情况发生在每次用户从程序切换离开的时候。
&&&& 还有一点很重要,就是能够请求DirectInput缓冲键盘信息。这要求提供一个缓冲区并使用SetProperty为设备设置缓冲区大小。在本文中没有篇幅讨论这一技术,但这一技术在程序不能相当频繁的检查键盘状态时非常有用。用户有可能在程序中两次GetDeviceState调用之间按下又松开了一个键,如果DirectInput不缓冲键盘数据的化,这种击键动作就丢失了。
&&& 游戏杆非常好玩。与其好听的名称(Joystick——原意为欢乐杆)相符,这种设备为游戏体验添加了许多乐趣,同时也为程序员的体验添加了一些东西。正常情况下,通过调用IdirectInput接口的CreateDevice成员得到IdirectInputDevice接口(和对象),这对游戏杆也适用。
&&& &但是开发人员都希望立即将接口升级到IDirectInputDevice2,那么可以象下面这样使用QueryInterface调用请求CreateDevice返回新的接口:
hr = lpDIDeviceJoystickTemp-&QueryInterface(
IID_IDirectInputDevice2,
(void **) &g_lpDIDeviceJoystick);
&&&& 如果成功,就可以释放原来的接口,开始使用漂亮的新IDirectInputDevice2接口。但是为什么要这么做呢?IDirectInputDevice2接口提供IdirectInputDevice的所有功能,而且还有另外两个重要特性:支持查询设备和支持力反馈设备。
&&&& 其次,需要设置上的一些考虑。还记得SetDataFormat定义了GetDeviceState返回的数据的类型。对于游戏杆设备,使用c_dfDIJoystick或c_dfDIJoystick2两个预定义变量之一,将返回数据的类型设置为DIJOYSTATE或DIJOYSTATE2结构。选择哪种主要取决于要使用游戏杆哪种类型的特性。浏览这些结构中的成员应该对弄清这个问题有帮助。
&&&& 同所有输入设备一样,要为游戏杆设置数据格式和协作级别。游戏杆往往比键盘需要更多一点注意。这是因为现在还几乎没有功能完美的游戏杆,所以程序应该检查以确保控制的设备能满足要求。如果不能,就调整要求或者提醒用户游戏杆太落后!设备的能力可以并且应该调用IdirectInputDevice接口的成员函数GetCapabilities探测。
&&&& 这就引出了适用于所有DirectX组件的另一个讨论点。DirectX为多种设备提供广泛的支持。软件开发环境和使用环境可能有很大差别,不同的计算机支持不同水平的DirectX功能。编写好使用DirectX的软件,需要检查硬件的能力。最差的情况下,如果某个功能不支持,可以退出程序。最好的情况当然是程序能够聪明地根据缺少的特性调整本身的需求。
&&&& 在开始从设备得到输入之前,需要设置设备的特性。这些特性包括象返回值的范围、游戏杆的中心点等此类的细节。这一工作由函数SetProperty完成,相当复杂。
&&&& SetProperty设置设备的一个特性。首先,必须使用关于要改变的设置的一些信息填写一个数据结构。请参考Platform SDK中的文档,得到所有数据结构。每个结构都以一个DIPROPHEADER结构开始,此结构中填写描述要改变的设置的信息。然后,用特定于所改变的设置的数据填写结构中剩余的部分。最后,调用SetProperty,参数是GUID和指向结构中DIPROPHEADER部分的指针。下面的代码片段将游戏杆的垂直范围设置为–100到100:
DIPROPRANGE
dipRange.diph.dwSize
= sizeof(dipRange);
dipRange.diph.dwHeaderSize = sizeof(dipRange.diph);
dipRange.diph.dwObj
= DIJOFS_Y;
dipRange.diph.dwHow
= DIPH_BYOFFSET;
dipRange.lMin
dipRange.lMax
g_lpDIDeviceJoystick-&SetProperty( DIPROP_RANGE,
&dipRange.diph) ;
&&&& 此结构中最难懂的部分是diph.dwObj和diph.dwHow。diph.dwHow描述diph.dwObj中保存何种信息。diph.dwObj实际描述哪个属性被设置。大多数情况下,diph.dwHow的值是DIPH_BYOFFSET,diph.dwObj的值是传递给SetDataFormat的结构中一个预定义的偏移。
&&&& 应该指出能够列举设备的对象,包括按钮和其它特点。这一工作由EnumObjects函数完成。这样做时,应该提供一个对象标志符。将此标志符传递给diph.dwObj成员,将diph.dwHow成员填写为DIPH_BYID。
&&&& 在从设备读取数据之前,至少要为设备的X和Y坐标轴设置最小和最大值。设置好设备属性后,就可以获得设备并开始从设备获得数据。从游戏杆获取数据与从键盘或鼠标获取数据不同,因为游戏杆是查询设备。
&&&& 键盘和鼠标会引发硬件中断,由系统中的驱动程序处理,并用来更新通过调用GetDeviceState由DirectInput返回的数据。查询设备(如大多数游戏杆)不产生硬件中断,因此,DirectInput必须被告知从设备获取状态信息。这一工作通过调用IDirectInputDevice2接口的Poll成员函数完成。此时也是检查&&&&
设备是否需要重新获得的适当时机。设备被成功查询后,就可以调用GetDeviceState获取状态信息。
&&&& 如果调用SetDataFormat时使用c_dfDIJoystick变量,那么GetDeviceState将用游戏杆当前的状态信息填充一个DIJOYSTATE结构。此结构的内容主要取决于物理设备的特性和SetProperty的设置。例如,如果结构中的lY成员等于-50,并且Y轴的范围设置为-100到100,那么就是说游戏杆在垂直方向上处于中心和最顶端的中间。程序中应该确保设备的范围设置为能合理满足需求的值。为了从游戏杆设备中获取数据,程序应该定期查询设备。
使用DirectInputEffect
&&& 首先,应该解释一些力反馈技术。力反馈设备是能够产生用户可以感觉到的力的设备,这些力叫作效果,例如颠簸效果或者持续的将操纵杆推向右上方的力。这些效果是“播放”出来的,效果由程序控制播放,或者对函数调用响应,或者对用户按键自动反应。
&&&& DirectInput目前支持大约一打不同的效果类型(见表5)。这些效果的范围从完全由程序控制的低级持续力效果,到由DirectInput或设备自己控制的高级倾斜或波动效果。效果有四种基本类型:持续力、倾斜效果、周期效果和条件。持续力是单一方向上不改变强度的力。倾斜效果是强度随时间线性变化的持续的力。周期效果是沿着给定的轴重复变化,其量级或者力的强度由周期效果定义。条件是对用户与游戏杆的交互作用做出响应的效果。这种效果可能是象一根弹簧,操纵杆向某个方向推得越远,反弹力就越强。
表5:DirectInput效果的类型
使用方法注解
GUID_ConstantForce
固定强度、特定方向的持续拉力。
使用DICONSTANT力结构作为DIEFFECT结构的一部分实现持续力。
GUID_CustomForce
一序列持续力下传到设备,按顺序播放。
DICUSTOMFORCE结构被用来定义力。
GUID_Damper
随沿坐标轴的移动增加的条件效果。
实现这种效果的特定类型结构是DICONDITION结构。条件效果通常不支持包。
GUID_Friction
阻碍沿坐标轴移动的条件效果。
实现这种效果的特定类型结构是DICONDITION结构。条件效果通常不支持包。
GUID_Inertia
随沿坐标轴移动的加速度增加的条件效果。
实现这种效果的特定类型结构是DICONDITION结构。条件效果通常不支持包。
GUID_RampForce
特定方向上大小线性增加或减小的拉力。
DIRAMPFORCE结构被用来作为DIEFFECT结构中的类型相关部分。
GUID_SawtoothDown
力瞬间达到最大然后线性减小到最小的周期效果。
需要的特定类型结构是DIPERIODIC结构。
GUID_SawtoothUp
力从最小线性增加到最大然后瞬间降到最小的周期效果
需要的特定类型结构是DIPERIODIC结构。
力正弦变化的周期效果。
需要的特定类型结构是DIPERIODIC结构。
GUID_Spring
力随到某个中点的相对距离而增大的条件效果。
实现这种效果的特定类型结构是DICONDITION结构。条件效果通常不支持包。
GUID_Square
力瞬时在最大与最小之间转变的周期效果。
需要的特定类型结构是DIPERIODIC结构。
GUID_Triangle
力在最大与最小之间线性变化的周期效果。
需要的特定类型结构是DIPERIODIC结构。
&&&& 下面所有与力反馈游戏杆有关的工作都是针对Microsoft SideWinder Force Feedback Pro游戏杆,这就是说,本文中的某些细节对其它设备可能多少会产生一些问题。
&&&& 在创建力反馈效果以前先获得设备是一个不错的想法。虽然这不是必须的,但是在效果能够被下传到设备前必须要获得设备。这一点对于播放对用户按下按钮做出反应的力效果尤其重要。
&&&& 要创建效果,首先要为每个打算使用的效果创建DirectInputEffect对象的实例。这一工作通过调用IDirectInputDevice2接口的CreateEffect成员函数完成。此函数需要效果的GUID,以及指向DIEFFECT结构的指针,该结构中填写的是效果的细节。最后,CreateEffect返回一个指向IdirectInputEffect接口的指针,该指针的地址是CreateEffect的一个参数。这个调用的核心部分集中在DIEFFECT结构的填充。
&&&& DIEFFECT结构如下定义:
typedef struct {
DWORD dwSampleP
DWORD dwTriggerB
DWORD dwTriggerRepeatI
LPDWORD rgdwA
LPLONG rglD
LPDIENVELOPE lpE
DWORD cbTypeSpecificP
LPVOID lpvTypeSpecificP
} DIEFFECT, *LPDIEFFECT;
dwSize成员是此结构的字节数。DwFlags指出效果使用的坐标类型,以及是使用偏移方法还是ID方法描述按钮(就向前面说明的SetProperty)。通常情况下,可以设置为DIEFF_CARTESIAN|DIEFF_OBJECTOFFSETS,即按钮采用偏移描述,坐标使用XYZ坐标形式。
DwDuration说明效果播放多少毫秒。注意dwDuration可以设为INFINITE。DwSamplePeriod说明效果播放一个周期花费多少毫秒。不同设备支持不同的周期。实际中,SideWinder游戏杆支持的周期不大于1秒,不小于1/80秒。DwGain可以看作效果的主要量,因为它说明效果多么有力。此值的范围是0到10000。
DwTriggerButton和dwTriggerRepeatInterval用来设置触发效果播放的按钮,以及重复频率。当然,可以通过将dwTriggerButton的值设置为DIEB_NOTRIGGER来将效果设置为与按钮无关。否则,dwFlags定义通过ID还是偏移方式描述按钮。因为偏移方式不需要调用EnumObjects,所以一般可以将值指定为DIJOFS_
BUTTON0和DIJOFS_BUTTON1。
CAxes成员说明效果将影响几个轴。RgdwAxes指向一个描述所包含的轴的DWORD数组,数组中每个轴是一个成员。同按钮一样,轴也是用偏移或者ID来指明。一般的偏移值包括DIJOFS_X和DIJOFS_Y。
&&&& 同样,rglDirection成员指向一个long型数组,每个轴是一个成员。在笛卡儿坐标中,(Y=-1,X=1)与(Y=-10,X=10)描述的是同一个方向。这就是说,如果想得到一个不是45度整数倍方向上的斜的力,就应该调整两个值的相对大小。例如,(Y=-10,X=1)描述与上面例子在同一象限的方向,但却明显靠近Y轴。
效果也可以有描述它们的包。填充一个DIENVELOPE结构,并将其地址填写到lpEnvelope成员就可以完成。包可以在一段时间内影响效果的数量或力量。其中,起动水平是效果的开始变化点,启动时间说明效果达到力量保持阶段花费多少毫秒。衰减水平是效果在包最后达到的水平,衰减时间是衰减用掉了多少豪秒。包可以用来制造初始状态较强,然后慢慢衰减的力效果。图1中描绘了包如何改变效果。
图1:包效果
&&&& DIEFFECT结构的最后两个成员是cbTypeSpecificParams和lpvTypeSpecificParams。它们保存特定于所创建效果类型的结构的字节数和地址。特定类型的效果使用何种结构的信息见表5。
&&&& 填写完这个结构并调用CreateEffect后,就会获得指向IdirectInputEffect接口的指针,现在可以使用此接口播放效果,改变效果等。如果没有将效果联系到按钮,就必须用IdirectInputEffect接口的Start和Stop成员播放和停止效果。如果效果与按钮关联,那么在创建时下传到设备;否则,效果在播放时自动下传到设备。如果程序必须重新获得设备,那么所有与按钮相关的效果必须通过明确的调用Download成员才能下传到设备。
&&&& 效果能够用Unload成员卸载,也能够通过向SetParameters成员函数传递新的DIEFFECT结构重新设置参数。当程序用完效果后,必须调用接口的Release成员。
图2:演示程序
&&&& 首先,应该建立演示代码并运行,应该能看到一个游戏杆配置窗口(见图2)。使用游戏杆可以移动中间的人,在窗口的左上角是坐标和输入状态信息。如果有力反馈游戏杆,那么通过按下按钮1和2应该能感觉到一对不同的力。如果将小人撞到窗口的边缘,应该能感到碰撞效果。
&&&& 这个例子说明了DirectInput的使用。这里仍然有相当数量的代码与DirectInput没有直接关系。这些代码根据功能划分成模块。Main.cpp是基本的WinMain样板文件和窗口创建代码。除了调用初始化函数外,这部分代码基本上与本文的其它部分没有关系。它创建窗口,进入消息循环。WndProc.cpp包含程序窗口的窗口过程。
&&&& Demo.cpp开始了有意义的代码。不论何时提到“demo”,都是指程序游戏。例如,InitDemo函数为图形设置状态数据并创建一些所需的时间和线程。除了初始化,此演示程序运行在第二个线程中。该线程尝试读取输入并刷新状态数据,每秒进行32次。然后使窗口无效,从而让主线程重新绘制窗口。这就是说,输入和状态变化的一个反复,或者说一个演示周期,大约有1/32秒。所以,不管显示刷新得多么频繁,输入响应速度都会保持一致。
&&&& DX.cpp包含DirectX需要的非常小的初始化和结束处理,然后调用完成特殊DirectInput工作的函数。除了CoInitialize和CoUninitialize外,DXInput模块包含本文中提到的所有内容。函数按照演示程序中用到的顺序列出,每个只列一次。注意,DirectInput的大部分工作在初始化中完成。冗长的任务划分成几个函数列在表6中。
表6:DXInput.cpp的函数
InitDirectInput
为系统键盘初始化DirectInput对象和DirectInputDevice对象。
列举设备的回调函数。此函数为系统中安装的第一个游戏杆创建DirectInputDevice。
InitForceFeedback
如果找到游戏杆是适应力反馈的,此函数就为力反馈效果进行一些设置。
InitRampEffect, InitBumpEffects, InitWavyEffect
这些函数每个都设置一个效果。这些效果演示了DirectInput中几种不同的效果,并且应该对创建新效果有用。
&&&& 这个模块中的另一个要点是演示程序重复调用的函数。ForceEffect播放一个存在的效果,GetKeyboardInput获得键盘输入,GetJoystickInput获得游戏杆输入。最后UnInitDirectInput结束所有的一切。
本文已收录于以下专栏:
相关文章推荐
不知不觉中,Windows下的游戏和多媒体程序已经开始流行。硬件变得越来越快,Windows也变得更加灵活。自从Microsoft发布了DirectX,游戏开发人员对其它平台已经越来越不感兴趣了。许多...
DirectX 9.0高级游戏编程(第3章)--使用DirectInput进行通信 收藏 概述 得到用户的输入可能是任何计算机游戏最重要的部分。如果没有用户输入,那么无论多时髦的图形或者多伟大的音效,...
DirectX 9.0高级游戏编程(第3章)--使用DirectInput进行通信 收藏 概述 得到用户的输入可能是任何计算机游戏最重要的部分。如果没有用户输入,那么无论多时髦的图形或者多伟大的音效,...
在本篇文章中,我们一起详细探索了DirectInput这套在PC游戏即时控制方面一手遮天的API。下面先来看一下这篇一万多字文章的大体脉络。首先我们对DirectInput接口进行了整体上的讲解,然后...
1. 创建力反馈资源1.1 在内容浏览器中点击Add New,并选择Miscellaneous&Force Feedback Effect。资源默认包含一个通道,但可以进行添加。
1.2 选择力反馈...
//驱动代码(中断传输)#include
view plaincopy
class=&cpp& name=&code&&//驱动代码(中断传输)#include      #include ...
Friends are going to play console. They have two joysticks and only one charger for them. Initially ...
他的最新文章
讲师:汪剑
讲师:刘道宽
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)

我要回帖

更多关于 北通游戏手柄 的文章

 

随机推荐