在我的上一篇博客中(http://blog.csdn.net/liyuanbhu/article/details/51714045),介绍了通过 multimedia joystick API 来访问游戏手柄的基本方法。

最后说到了利用 joySetCapture 函数监听手柄事件的方式并不是非常的好用。建议大家字节写个监听线程,有针对性的监听需要的事件。这里,我把我以前写的一份代码放上来。代码是基于 Qt 的,监听了按键、摇杆和视觉头盔的状态,在状态发生改变时发出Qt 的信号。

按键对应两个信号:

  1. void Joy_ButtonPressed(int i);
  2. void Joy_ButtonReleased(int i);

摇杆分为两种模式:SWITCH_MODE 和 COORDINATE_MODE

SWITCH_MODE 模式下,输出四个方向的开关量。对应的信号是:

  1. void Joy_MoveForward();
  2. void Joy_MoveBackward();
  3. void Joy_MoveForwardStop();
  4. void Joy_MoveBackwardStop();
  5. void Joy_MoveLeft();
  6. void Joy_MoveRight();
  7. void Joy_MoveLeftStop();
  8. void Joy_MoveRightStop();

COORDINATE_MODE 模式直接输出坐标值(只有在摇杆位置发生变化时才会有输出)。

  1. void Joy_Position(int x, int y);

视觉头盔模拟了摇杆的开关量模式。对应的信号同样是:

  1. void Joy_MoveForward();
  2. void Joy_MoveBackward();
  3. void Joy_MoveForwardStop();
  4. void Joy_MoveBackwardStop();
  5. void Joy_MoveLeft();
  6. void Joy_MoveRight();
  7. void Joy_MoveLeftStop();
  8. void Joy_MoveRightStop();

具体的代码不用过多介绍,主要就是几个状态机。下面贴出代码来。

首先是头文件:

  1. #ifndef JOYSTICK_H
  2. #define JOYSTICK_H
  3. #include <QObject>
  4. #include <QThread>
  5. #include <Windows.h>
  6. #include <Mmsystem.h>
  7. class JoyStick;
  8. /**
  9. * @brief The JoyStickThread class
  10. * @details 内部类,定时轮询 JoyStick 的状态。
  11. */
  12. class JoyStickThread : public QThread
  13. {
  14. public:
  15. explicit JoyStickThread();
  16. void setJoyStick(JoyStick *joystick);
  17. void run();
  18. void stop();
  19. private:
  20. void Coordinate_StateMachine(int xPos, int yPos);
  21. void AxisX_StateMachine(int xPos);
  22. void AxisY_StateMachine(int yPos);
  23. void Button_StateMachine(int button);
  24. void POV_StateMachine_Axis(int pov);
  25. void POV_StateMachine(int pov);
  26. int old_xPos;
  27. int old_yPos;
  28. int old_pov;
  29. bool pov_forward;
  30. bool pov_backward;
  31. bool pov_left;
  32. bool pov_right;
  33. bool pov_center;
  34. int m_button[16];
  35. JoyStick *m_joystick;
  36. bool m_run;
  37. };
  38. class JoyStick : public QObject
  39. {
  40. Q_OBJECT
  41. public:
  42. enum MODE{SWITCH_MODE, COORDINATE_MODE};
  43. /**
  44. * @brief JoyStick
  45. * @param mode SWITCH_MODE 模式时,摇杆输出开关量。COORDINATE_MODE 模式时,输出摇杆的位置。
  46. * @param parent
  47. */
  48. explicit JoyStick(enum MODE mode = SWITCH_MODE, QObject *parent = 0);
  49. enum MODE mode() const {return m_mode;}
  50. ~JoyStick();
  51. /**
  52. * @brief listen
  53. * @return 启动监听线程,之后就可以接收手柄的各种消息了。
  54. */
  55. bool listen();
  56. /**
  57. * @brief stop 停止监听线程,不需要接收手柄消息时可以调用这个函数。
  58. */
  59. void stop();
  60. signals:
  61. /// JoyStick 的摇杆的各种信号。
  62. /// 高级些的手柄是可以返回摇杆的坐标值的。
  63. /// 这里模仿的是工业摇杆,输出的都是开关量。
  64. /// 前后左右四组开关量。
  65. void Joy_MoveForward();
  66. void Joy_MoveBackward();
  67. void Joy_MoveForwardStop();
  68. void Joy_MoveBackwardStop();
  69. void Joy_MoveLeft();
  70. void Joy_MoveRight();
  71. void Joy_MoveLeftStop();
  72. void Joy_MoveRightStop();
  73. /// JoyStick 的摇杆位置。
  74. void Joy_Position(int x, int y);
  75. /**
  76. * @brief Joy_ButtonPressed 当手柄上某个按键被按下时发出这个信号
  77. * @param i 用来标志是哪个按键被按下了。
  78. */
  79. void Joy_ButtonPressed(int i);
  80. /**
  81. * @brief Joy_ButtonReleased 当手柄上某个按键被释放时发出这个信号
  82. * @param i 用来标志是哪个按键被释放了。
  83. */
  84. void Joy_ButtonReleased(int i);
  85. /// 以下是视觉头盔的各种信号
  86. void Joy_POVForward();
  87. void Joy_POVBackward();
  88. void Joy_POVLeft();
  89. void Joy_POVRight();
  90. void Joy_POVForwardLeft();
  91. void Joy_POVForwardRight();
  92. void Joy_POVBackwardLeft();
  93. void Joy_POVBackwardRight();
  94. /**
  95. * @brief Joy_POVCentered 当视觉头盔从前8种状态恢复到默认状态时发出这个信号。
  96. */
  97. void Joy_POVCentered();
  98. private:
  99. enum MODE m_mode;
  100. bool m_valid;
  101. JoyStickThread m_thread;
  102. };
  103. #endif // JOYSTICK_H

下面是cpp 文件:

  1. #include "joystick.h"
  2. #include <Windows.h>
  3. #include <QDebug>
  4. JoyStick::JoyStick(enum MODE mode, QObject *parent) : QObject(parent)
  5. {
  6. m_mode = mode;
  7. m_valid = false;
  8. m_thread.setJoyStick(this);
  9. JOYINFO joyinfo;
  10. if( joyGetNumDevs() > 0 && joyGetPos(JOYSTICKID1, &joyinfo) != JOYERR_UNPLUGGED )
  11. {
  12. qDebug() << "JoyStick Init success!";
  13. m_valid = true;
  14. }
  15. }
  16. JoyStick::~JoyStick()
  17. {
  18. m_thread.stop();
  19. m_thread.wait();
  20. }
  21. bool JoyStick::listen()
  22. {
  23. m_thread.start();
  24. return true;
  25. }
  26. void JoyStick::stop()
  27. {
  28. if(m_thread.isRunning())
  29. {
  30. m_thread.stop();
  31. m_thread.wait();
  32. }
  33. }
  34. JoyStickThread::JoyStickThread()
  35. {
  36. m_run = 1;
  37. old_xPos = 32767;
  38. old_yPos = 32767;
  39. for(int i = 0; i < 16; i++)
  40. {
  41. m_button[i] = 0;
  42. }
  43. old_pov = JOY_POVCENTERED;
  44. pov_forward = false;
  45. pov_backward = false;
  46. pov_left = false;
  47. pov_right = false;
  48. pov_center = true;
  49. }
  50. void JoyStickThread::stop()
  51. {
  52. m_run = 0;
  53. }
  54. void JoyStickThread::setJoyStick(JoyStick *joystick)
  55. {
  56. m_joystick = joystick;
  57. }
  58. void JoyStickThread::run()
  59. {
  60. //JOYINFO joyinfo;
  61. JOYINFOEX joyinfoex;
  62. joyinfoex.dwSize = sizeof(JOYINFOEX);
  63. joyinfoex.dwFlags = JOY_RETURNALL;
  64. while(m_run)
  65. {
  66. // if(joyGetPos(JOYSTICKID1, &joyinfo) == JOYERR_NOERROR)
  67. // {
  68. // //qDebug() << joyinfo.wXpos;
  69. // AxisX_StateMachine(joyinfo.wXpos);
  70. // AxisY_StateMachine(joyinfo.wYpos);
  71. // Button_StateMachine(joyinfo.wButtons);
  72. // }
  73. if(joyGetPosEx(JOYSTICKID1, &joyinfoex) == JOYERR_NOERROR)
  74. {
  75. if(m_joystick->mode() == JoyStick::SWITCH_MODE)
  76. {
  77. AxisX_StateMachine(joyinfoex.dwXpos);
  78. AxisY_StateMachine(joyinfoex.dwYpos);
  79. }
  80. else
  81. {
  82. Coordinate_StateMachine(joyinfoex.dwXpos, joyinfoex.dwYpos);
  83. }
  84. Button_StateMachine(joyinfoex.dwButtons);
  85. POV_StateMachine_Axis(joyinfoex.dwPOV);
  86. }
  87. msleep(50);
  88. }
  89. }
  90. void JoyStickThread::POV_StateMachine(int pov)
  91. {
  92. if(pov != old_pov)
  93. {
  94. //qDebug() << pov;
  95. if( pov == JOY_POVFORWARD )
  96. {
  97. emit m_joystick->Joy_POVForward();
  98. }
  99. if( pov == JOY_POVFORWARD + 4500 )
  100. {
  101. emit m_joystick->Joy_POVForwardRight();
  102. }
  103. if( pov == JOY_POVRIGHT )
  104. {
  105. emit m_joystick->Joy_POVRight();
  106. }
  107. if( pov == JOY_POVRIGHT + 4500 )
  108. {
  109. emit m_joystick->Joy_POVBackwardRight();
  110. }
  111. if( pov == JOY_POVBACKWARD )
  112. {
  113. emit m_joystick->Joy_POVBackward();
  114. }
  115. if( pov == JOY_POVBACKWARD + 4500 )
  116. {
  117. emit m_joystick->Joy_POVBackwardLeft();
  118. }
  119. if( pov == JOY_POVLEFT )
  120. {
  121. emit m_joystick->Joy_POVLeft();
  122. }
  123. if( pov == JOY_POVLEFT + 4500 )
  124. {
  125. emit m_joystick->Joy_POVForwardLeft();
  126. }
  127. if( pov == JOY_POVCENTERED )
  128. {
  129. emit m_joystick->Joy_POVCentered();
  130. }
  131. old_pov = pov;
  132. }
  133. }
  134. void JoyStickThread::POV_StateMachine_Axis(int pov)
  135. {
  136. if(pov != old_pov)
  137. {
  138. //qDebug() << pov;
  139. if( pov == JOY_POVFORWARD )
  140. {
  141. if(pov_forward == false)
  142. {
  143. pov_forward = true;
  144. emit m_joystick->Joy_MoveForward();
  145. //qDebug() << "JOY_POVFORWARD";
  146. }
  147. if(pov_left == true)
  148. {
  149. emit m_joystick->Joy_MoveLeftStop();
  150. //qDebug() << "JOY_POVLEFT RETURN";
  151. }
  152. if(pov_right == true)
  153. {
  154. emit m_joystick->Joy_MoveRightStop();
  155. //qDebug() << "JOY_POVRIGHT RETURN";
  156. }
  157. pov_left = false;
  158. pov_right = false;
  159. }
  160. if( pov == JOY_POVFORWARD + 4500 )
  161. {
  162. if(pov_forward == false)
  163. {
  164. pov_forward = true;
  165. emit m_joystick->Joy_MoveForward();
  166. //qDebug() << "JOY_POVFORWARD";
  167. }
  168. if(pov_right == false)
  169. {
  170. pov_right = true;
  171. emit m_joystick->Joy_MoveRight();
  172. //qDebug() << "JOY_POVRIGHT";
  173. }
  174. }
  175. if( pov == JOY_POVRIGHT )
  176. {
  177. if(pov_right == false)
  178. {
  179. pov_right = true;
  180. emit m_joystick->Joy_MoveRight();
  181. //qDebug() << "JOY_POVRIGHT";
  182. }
  183. if(pov_forward == true)
  184. {
  185. emit m_joystick->Joy_MoveForwardStop();
  186. //qDebug() << "JOY_POVFORWARD RETURN";
  187. }
  188. if(pov_backward == true)
  189. {
  190. emit m_joystick->Joy_MoveBackwardStop();
  191. //qDebug() << "JOY_POVBACKWARD RETURN";
  192. }
  193. pov_forward = false;
  194. pov_backward = false;
  195. }
  196. if( pov == JOY_POVRIGHT + 4500 )
  197. {
  198. if(pov_right == false)
  199. {
  200. pov_right = true;
  201. emit m_joystick->Joy_MoveRight();
  202. // qDebug() << "JOY_POVRIGHT";
  203. }
  204. if(pov_backward == false)
  205. {
  206. pov_backward = true;
  207. emit m_joystick->Joy_MoveBackward();
  208. // qDebug() << "JOY_POVBACKWARD";
  209. }
  210. }
  211. if( pov == JOY_POVBACKWARD )
  212. {
  213. if(pov_backward == false)
  214. {
  215. pov_backward = true;
  216. emit m_joystick->Joy_MoveBackward();
  217. //qDebug() << "JOY_POVBACKWARD";
  218. }
  219. if(pov_left == true)
  220. {
  221. emit m_joystick->Joy_MoveLeftStop();
  222. //qDebug() << "JOY_POVLEFT RETURN";
  223. }
  224. if(pov_right == true)
  225. {
  226. emit m_joystick->Joy_MoveRightStop();
  227. //qDebug() << "JOY_POVRIGHT RETURN";
  228. }
  229. pov_left = false;
  230. pov_right = false;
  231. }
  232. if( pov == JOY_POVBACKWARD + 4500 )
  233. {
  234. if(pov_backward == false)
  235. {
  236. pov_backward = true;
  237. emit m_joystick->Joy_MoveBackward();
  238. //qDebug() << "JOY_POVBACKWARD";
  239. }
  240. if(pov_left == false)
  241. {
  242. pov_left = true;
  243. emit m_joystick->Joy_MoveLeft();
  244. // qDebug() << "JOY_POVLEFT";
  245. }
  246. }
  247. if( pov == JOY_POVLEFT )
  248. {
  249. if(pov_left == false)
  250. {
  251. pov_left = true;
  252. emit m_joystick->Joy_MoveLeft();
  253. //qDebug() << "JOY_POVLEFT";
  254. }
  255. if(pov_forward == true)
  256. {
  257. emit m_joystick->Joy_MoveForwardStop();
  258. //qDebug() << "JOY_POVFORWARD RETURN";
  259. }
  260. if(pov_backward == true)
  261. {
  262. emit m_joystick->Joy_MoveBackwardStop();
  263. //qDebug() << "JOY_POVBACKWARD RETURN";
  264. }
  265. pov_backward = false;
  266. pov_forward = false;
  267. }
  268. if( pov == JOY_POVLEFT + 4500 )
  269. {
  270. if(pov_left == false)
  271. {
  272. pov_left = true;
  273. emit m_joystick->Joy_MoveLeft();
  274. //qDebug() << "JOY_POVLEFT";
  275. }
  276. if(pov_forward == false)
  277. {
  278. pov_forward = true;
  279. emit m_joystick->Joy_MoveForward();
  280. //qDebug() << "JOY_POVFORWARD";
  281. }
  282. }
  283. if( pov == JOY_POVCENTERED )
  284. {
  285. if(pov_forward == true)
  286. {
  287. emit m_joystick->Joy_MoveForwardStop();
  288. //qDebug() << "JOY_POVFORWARD RETURN";
  289. }
  290. if(pov_backward == true)
  291. {
  292. emit m_joystick->Joy_MoveBackwardStop();
  293. //qDebug() << "JOY_POVBACKWARD RETURN";
  294. }
  295. if(pov_left == true)
  296. {
  297. emit m_joystick->Joy_MoveLeftStop();
  298. //qDebug() << "JOY_POVLEFT RETURN";
  299. }
  300. if(pov_right == true)
  301. {
  302. emit m_joystick->Joy_MoveRightStop();
  303. //qDebug() << "JOY_POVRIGHT RETURN";
  304. }
  305. pov_forward = false;
  306. pov_right = false;
  307. pov_left = false;
  308. pov_backward = false;
  309. //qDebug() << "JOY_POVCENTERED";
  310. }
  311. old_pov = pov;
  312. }
  313. }
  314. void JoyStickThread::Button_StateMachine(int button)
  315. {
  316. //if( button )
  317. //qDebug() << QString::number(button, 16);
  318. const int mask[16] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768};
  319. for(int i = 0; i < 12; i++)
  320. {
  321. int n = button & mask[i];
  322. if(n ^ m_button[i])
  323. {
  324. m_button[i] = n;
  325. if( n )
  326. {
  327. emit m_joystick->Joy_ButtonPressed(i + 1);
  328. //qDebug() << "ButtonPressed(" << i + 1 << ")";
  329. }
  330. else
  331. {
  332. emit m_joystick->Joy_ButtonReleased(i + 1);
  333. //qDebug() << "ButtonReleased(" << i + 1 << ")";;
  334. }
  335. }
  336. }
  337. }
  338. void JoyStickThread::Coordinate_StateMachine(int xPos, int yPos)
  339. {
  340. if(xPos == old_xPos && yPos == old_yPos)
  341. {
  342. return;
  343. }
  344. old_xPos = xPos;
  345. old_yPos = yPos;
  346. emit m_joystick->Joy_Position(xPos, yPos);
  347. }
  348. void JoyStickThread::AxisX_StateMachine(int xPos)
  349. {
  350. if(xPos == old_xPos) return;
  351. switch(xPos)
  352. {
  353. case 0:
  354. emit m_joystick->Joy_MoveLeft();
  355. break;
  356. case 32767:
  357. if(old_xPos == 0)
  358. {
  359. emit m_joystick->Joy_MoveLeftStop();
  360. }
  361. else
  362. {
  363. emit m_joystick->Joy_MoveRightStop();
  364. }
  365. break;
  366. case 65535:
  367. emit m_joystick->Joy_MoveRight();
  368. break;
  369. }
  370. old_xPos = xPos;
  371. }
  372. void JoyStickThread::AxisY_StateMachine(int yPos)
  373. {
  374. if(yPos == old_yPos) return;
  375. switch(yPos)
  376. {
  377. case 0:
  378. emit m_joystick->Joy_MoveForward();
  379. break;
  380. case 32767:
  381. if(old_xPos == 0)
  382. {
  383. emit m_joystick->Joy_MoveForwardStop();
  384. }
  385. else
  386. {
  387. emit m_joystick->Joy_MoveBackwardStop();
  388. }
  389. break;
  390. case 65535:
  391. emit m_joystick->Joy_MoveBackward();
  392. break;
  393. }
  394. old_yPos = yPos;
  395. }

具体的使用方法很简答,建立对象后,只要调用 listen() 函数开始监听就可以了。

当然在监听之前,还要连接好需要的信号和槽。

游戏手柄(JoyStick)编程学习笔记(2)的更多相关文章

  1. JAVA GUI编程学习笔记目录

    2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...

  2. Linux Shell编程学习笔记——目录(附笔记资源下载)

    LinuxShell编程学习笔记目录附笔记资源下载 目录(?)[-] 写在前面 第一部分 Shell基础编程 第二部分 Linux Shell高级编程技巧 资源下载 写在前面 最近花了些时间学习She ...

  3. DirectX 11游戏编程学习笔记之8: 第6章Drawing in Direct3D(在Direct3D中绘制)(习题解答)

            本文由哈利_蜘蛛侠原创,转载请注明出处.有问题欢迎联系2024958085@qq.com         注:我给的电子版是700多页,而实体书是800多页,所以我在提到相关概念的时候 ...

  4. 多线程编程学习笔记——async和await(一)

    接上文 多线程编程学习笔记——任务并行库(一) 接上文 多线程编程学习笔记——任务并行库(二) 接上文 多线程编程学习笔记——任务并行库(三) 接上文 多线程编程学习笔记——任务并行库(四) 通过前面 ...

  5. 多线程编程学习笔记——async和await(二)

    接上文 多线程编程学习笔记——async和await(一) 三.   对连续的异步任务使用await操作符 本示例学习如何阅读有多个await方法方法时,程序的实际流程是怎么样的,理解await的异步 ...

  6. 多线程编程学习笔记——async和await(三)

    接上文 多线程编程学习笔记——async和await(一) 接上文 多线程编程学习笔记——async和await(二) 五.   处理异步操作中的异常 本示例学习如何在异步函数中处理异常,学习如何对多 ...

  7. 多线程编程学习笔记——使用异步IO(一)

    接上文 多线程编程学习笔记——使用并发集合(一) 接上文 多线程编程学习笔记——使用并发集合(二) 接上文 多线程编程学习笔记——使用并发集合(三) 假设以下场景,如果在客户端运行程序,最的事情之一是 ...

  8. 多线程编程学习笔记——编写一个异步的HTTP服务器和客户端

    接上文 多线程编程学习笔记——使用异步IO 二.   编写一个异步的HTTP服务器和客户端 本节展示了如何编写一个简单的异步HTTP服务器. 1.程序代码如下. using System; using ...

  9. 多线程编程学习笔记——异步调用WCF服务

    接上文 多线程编程学习笔记——使用异步IO 接上文 多线程编程学习笔记——编写一个异步的HTTP服务器和客户端 接上文 多线程编程学习笔记——异步操作数据库 本示例描述了如何创建一个WCF服务,并宿主 ...

  10. 【Visual C++】游戏编程学习笔记之四:透明动画实现

    本系列文章由@二货梦想家张程 所写,转载请注明出处. 本文章链接:http://blog.csdn.net/terence1212/article/details/44224963 作者:ZeeCod ...

随机推荐

  1. ArrayBlockingQueue 阻塞队列和 Semaphore 信号灯的应用

    import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; public cl ...

  2. c# 托管和非托管的介绍

    在.net 编程环境中,系统的资源分为托管资源和非托管资源. 对于托管的资源的回收工作,是不需要人工干预回收的,而且你也无法干预他们的回收,所能够做的 只是了解.net CLR如何做这些操作.也就是说 ...

  3. 如何让触摸事件穿透一个View

    如何让触摸事件穿透一个View 偶然间发现,如何屏蔽或者让触摸事件穿透一个view是一个很简单的事情. 现象: 源码: // // ViewController.m // UserInteractio ...

  4. UNIX高级环境编程(1)File I/O

    引言: Unix系统中主要的文件操作包括: open read write lseek close unbuffered IO和standard I/O相对应,后面的章节我们会讨论这两者的区别. 在讨 ...

  5. Elasticsearch部分节点不能发现集群(脑裂)问题处理

    **现象描述** es1,es2,es3三台es组成一个集群,集群状态正常, 当es1 服务器重启后,es1不能加到集群中,自己选举自己为master,这就产生了es集群中所谓的“脑裂” , 把es1 ...

  6. Linux blkid命令详解

    blkid命令对查询设备上所采用文件系统类型进行查询.blkid主要用来对系统的块设备(包括交换分区)所使用的文件系统类型.LABEL.UUID等信息进行查询.要使用这个命令必须安装e2fsprogs ...

  7. CSS学习摘要-浮动与清除浮动

    以下从浮动到BFC的段落 摘自MDN 网络开发者 float 浮动 float CSS属性指定一个元素应沿其容器的左侧或右侧放置,允许文本和内联元素环绕它.该元素从网页的正常流动中移除,尽管仍然保持部 ...

  8. Test checkout of feature 'Compiler' failed 解决方法(转载)

    Test checkout of feature 'Compiler' failed.   2014a的解决办法 适用于已安装compiler但破解不完全的, ht—tp://pan.baidu.co ...

  9. September 19th 2017 Week 38th Tuesday

    Live boldly. Push yourself. Don't settle. 勇敢生活,突破自我,永不设限! Don't indulge in the past, whether it was ...

  10. [EffectiveC++]item28:避免返回handles指向对象内部成分

    可以先参考一个帖子:http://bbs.csdn.net/topics/390731394?page=1