游戏手柄(JoyStick)编程控制的一个简单代码(Qt)
2017-03-25 13:53
756 查看
最近买到一种USB 接口的三轴 8 个按键的Joystick。下面这个样子。
用在最近做的一个工控项目上效果还不错。这里把代码公开了。
Joystick 的控制我以前写过两篇博客:
http://blog.csdn.net/liyuanbhu/article/details/51714045
http://blog.csdn.net/liyuanbhu/article/details/54809858
第一篇博客中把原理基本都讲清楚了。所以这里就只贴代码了。
代码的基本思路就是建立一个监听线程,轮询 joystick 的状态。不同的状态输出不同的结果。因为我的项目中都是只用到一个Joystick,所以代码也没考虑多个 Joystick 的情况。
用在最近做的一个工控项目上效果还不错。这里把代码公开了。
Joystick 的控制我以前写过两篇博客:
http://blog.csdn.net/liyuanbhu/article/details/51714045
http://blog.csdn.net/liyuanbhu/article/details/54809858
第一篇博客中把原理基本都讲清楚了。所以这里就只贴代码了。
代码的基本思路就是建立一个监听线程,轮询 joystick 的状态。不同的状态输出不同的结果。因为我的项目中都是只用到一个Joystick,所以代码也没考虑多个 Joystick 的情况。
#ifndef JOYSTICK_H #define JOYSTICK_H #include <QThread> /** * 3 轴 8 按键 Joystick 的驱动程序。 * 使用的是微软的 multimedia joystick API。 * 没有使用更流行的 DirectInput 技术。 */ class JoystickThread : public QThread { Q_OBJECT public: explicit JoystickThread(QObject *parent = Q_NULLPTR); /** * @brief run 启动监听线程 */ void run(); /** * @brief stop 停止监听线程 */ void stop(); signals: /// 手柄 XY 轴的输出信号 /// 需 enableSignal(true), enableXYSignal(true) 才有效 void Joy_MoveForward(); void Joy_MoveBackward(); void Joy_MoveForwardStop(); void Joy_MoveBackwardStop(); void Joy_MoveLeft(); void Joy_MoveRight(); void Joy_MoveLeftStop(); void Joy_MoveRightStop(); /// 手柄 Z 轴的输出信号 /// 需 enableSignal(true), enableZSignal(true) 才有效 void Joy_MoveClockWise(); void Joy_MoveCCW(); void Joy_MoveClockWiseStop(); void Joy_MoveCCWStop(); /// 手柄按键的输出信号 /// 需 enableSignal(true), enableButtionSignal(true) 才有效 void Joy_Button1Pressed(); void Joy_Button2Pressed(); void Joy_Button3Pressed(); void Joy_Button4Pressed(); void Joy_Button5Pressed(); void Joy_Button6Pressed(); void Joy_Button7Pressed(); void Joy_Button8Pressed(); void Joy_Button1Released(); void Joy_Button2Released(); void Joy_Button3Released(); void Joy_Button4Released(); void Joy_Button5Released(); void Joy_Button6Released(); void Joy_Button7Released(); void Joy_Button8Released(); public slots: /** * @brief setXYThreshold 设置 XY 手柄的开启阈值。 * 由于手柄使用时间长了会由于机械问题在原点停不住。所以需要有个开启阈值。 * @param x x 阈值 * @param y y 阈值 */ void setXYThreshold(int x, int y); /** * @brief setZThreshold 设置 Z 手柄的开启阈值。 * @param z z 阈值 */ void setZThreshold(int z); /** * @brief enableSignal 可以用这个函数关闭所有的信号 * @param on */ void enableSignal(bool on) {m_signal = on;} /** * @brief enableXYSignal XY 手柄的使能控制,只有enableSignal(true)时才有效。 * 相当于对手柄的信号有两级控制,第一级是全局使能,第二级是这里的使能。 * @param on */ void enableXYSignal(bool on) {m_xy_signal = on;} void enableZSignal(bool on) {m_z_signal = on;} void enableButtionSignal(bool on ){m_button_signal = on;} /** * @brief setMonitorInterval 设置内部轮询的时间间隔 * @param interval 单位 ms,范围 20 - 10000。 */ void setMonitorInterval(int interval); private: int Axis_stateMachine(int pos, int threshold, int &old_pos); void AxisX_StateMachine(int xPos); void AxisY_StateMachine(int yPos); void AxisZ_StateMachine(int zPos); void Button_StateMachine(int button); int m_xThreshold; int m_yThreshold; int m_zThreshold; int old_xPos; int old_yPos; int old_zPos; int m_button[8]; bool m_run; bool m_valid; bool m_signal; bool m_xy_signal; bool m_z_signal; bool m_button_signal; int m_monitor_interval; }; #endif // JOYSTICK_H
#include "Joystick3D.h" #include <Windows.h> #include <QDebug> JoystickThread::JoystickThread(QObject *parent) :QThread(parent), m_valid(false), m_run(true), m_xThreshold(5000), m_yThreshold(5000), m_zThreshold(5000), old_xPos(0), old_yPos(0), old_zPos(0), m_signal(false), m_xy_signal(false), m_z_signal(false), m_button_signal(false), m_monitor_interval(50) { JOYINFO joyinfo; if( joyGetNumDevs() > 0 && joyGetPos(JOYSTICKID1, &joyinfo) != JOYERR_UNPLUGGED ) { m_valid = true; qDebug() << "m_valid = true"; } for(int i = 0; i < 8; i++) { m_button[i] = 0; } } void JoystickThread::stop() { m_run = 0; wait(); } void JoystickThread::setXYThreshold(int x, int y) { m_xThreshold = abs(x); m_yThreshold = abs(y); } void JoystickThread::setZThreshold(int z) { m_zThreshold = abs(z); } void JoystickThread::run() { JOYINFOEX joyinfoex; joyinfoex.dwSize = sizeof(JOYINFOEX); joyinfoex.dwFlags = JOY_RETURNALL; while(m_valid && m_run) { if(joyGetPosEx(JOYSTICKID1, &joyinfoex) == JOYERR_NOERROR) { AxisX_StateMachine(joyinfoex.dwXpos); AxisY_StateMachine(joyinfoex.dwYpos); AxisZ_StateMachine(joyinfoex.dwZpos); Button_StateMachine(joyinfoex.dwButtons); } msleep(m_monitor_interval); } } void JoystickThread::setMonitorInterval(int interval) { m_monitor_interval = qBound(20, interval, 10000); } int JoystickThread::Axis_stateMachine(int pos, int threshold, int &old_pos) { pos = pos - 32767; if(abs(pos) <= threshold) { pos = 0; } else if (pos > threshold) { pos = 1; } else { pos = -1; } if(pos == old_pos) return 0; int ret; switch(pos) { case -1: ret = -1; break; case 0: if(old_pos == -1) { ret = -2; } else { ret = 2; } break; case 1: ret = 1; break; } //qDebug() << "o = " << old_pos << ", " << pos << ", ret =" << ret; old_pos = pos; return ret; } void JoystickThread::AxisX_StateMachine(int xPos) { int ret = Axis_stateMachine(xPos, m_xThreshold, old_xPos); if(!m_signal || !m_xy_signal) return; switch(ret) { case -1: emit Joy_MoveLeft(); break; case -2: emit Joy_MoveLeftStop(); break; case 2: emit Joy_MoveRightStop(); break; case 1: emit Joy_MoveRight(); break; default: break; } } void JoystickThread::AxisY_StateMachine(int yPos) { int ret = Axis_stateMachine(yPos, m_yThreshold, old_yPos); if(!m_signal || !m_xy_signal) return; switch(ret) { case -1: emit Joy_MoveForward(); break; case -2: emit Joy_MoveForwardStop(); break; case 2: emit Joy_MoveBackwardStop(); break; case 1: emit Joy_MoveBackward(); break; default: break; } } void JoystickThread::AxisZ_StateMachine(int zPos) { int ret = Axis_stateMachine(zPos, m_zThreshold, old_zPos); if(ret == 0) return; //qDebug() << zPos - 32767 << ", " << ret; if(!m_signal || !m_z_signal) return; switch(ret) { case -1: emit Joy_MoveCCW(); break; case -2: emit Joy_MoveCCWStop(); break; case 2: emit Joy_MoveClockWiseStop(); break; case 1: emit Joy_MoveClockWise(); break; default: break; } } void JoystickThread::Button_StateMachine(int button) { const int mask[8] = {1, 2, 4, 8, 16, 32, 64, 128}; for(int i = 0; i < 8; i++) { int n = button & mask[i]; if(n ^ m_button[i]) // 如果当前 button 与以前的 button 不同 { m_button[i] = n; if(!m_signal || !m_button_signal) continue; if( n ) { qDebug() << "Joy_Button" << i+1 << "Pressed()"; switch (i + 1) { case 1: emit Joy_Button1Pressed(); break; case 2: emit Joy_Button2Pressed(); break; case 3: emit Joy_Button3Pressed(); break; case 4: emit Joy_Button4Pressed(); break; case 5: emit Joy_Button5Pressed(); break; case 6: emit Joy_Button6Pressed(); break; case 7: emit Joy_Button7Pressed(); break; case 8: emit Joy_Button8Pressed(); break; default: break; } } else { qDebug() << "Joy_Button" << i+1 << "Released()"; switch (i + 1) { case 1: emit Joy_Button1Released(); break; case 2: emit Joy_Button2Released(); break; case 3: emit Joy_Button3Released(); break; case 4: emit Joy_Button4Released(); break; case 5: emit Joy_Button5Released(); break; case 6: emit Joy_Button6Released(); break; case 7: emit Joy_Button7Released(); break; case 8: emit Joy_Button8Released(); break; default: break; } } } } }
相关文章推荐
- 一个简单的Java网络编程代码
- linux joystick 游戏手柄编程 (获取输入数据)
- 游戏手柄(JoyStick)编程学习笔记(1)
- 游戏手柄(JoyStick)编程学习笔记(2)
- 一个简单的示例讲解游戏游戏编程原理。附示例源码
- 游戏简单控制逻辑 一个轻量级的状态机
- 游戏手柄(JoyStick)编程学习笔记(2)
- 一个简单的猜谜游戏的代码(高级用户界面制作)
- 2.我的第一个JSP代码:java控制输出1-100之和,say hello并写一个简单的表格
- 游戏编程笔记-起步(一)一个简单的游戏-贪吃蛇
- 一个简单的游戏源代码
- java游戏开发--简单的几行代码就完成了驱动小精灵的编程
- 游戏手柄(JoyStick)编程学习笔记(2)
- apue编程之参考du代码利用递归写的一个简单的du命令的源代码
- UNIX-LINUX编程实践教程->第八章->实例代码注解->写一个简单的shell->在shell中启动另一个程序
- apue编程之参考df代码写的一个简单的df命令的源代码
- C#游戏编程之创建一个简单的卷轴射击游戏
- Tinyhttpd - 超轻量型Http Server,使用C语言开发,全部代码只有502行(包括注释),附带一个简单的Client(Qt也有很多第三方HTTP类)
- 游戏手柄(JoyStick)编程学习笔记(1)
- 游戏手柄(JoyStick)编程学习笔记(1)