游戏手柄(JoyStick)编程学习笔记(2)

您所在的位置:网站首页 手柄joystick 游戏手柄(JoyStick)编程学习笔记(2)

游戏手柄(JoyStick)编程学习笔记(2)

2024-04-07 20:07| 来源: 网络整理| 查看: 265

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

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

按键对应两个信号:

void Joy_ButtonPressed(int i); void Joy_ButtonReleased(int i);

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

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

void Joy_MoveForward(); void Joy_MoveBackward(); void Joy_MoveForwardStop(); void Joy_MoveBackwardStop(); void Joy_MoveLeft(); void Joy_MoveRight(); void Joy_MoveLeftStop(); void Joy_MoveRightStop();

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

void Joy_Position(int x, int y);

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

void Joy_MoveForward(); void Joy_MoveBackward(); void Joy_MoveForwardStop(); void Joy_MoveBackwardStop(); void Joy_MoveLeft(); void Joy_MoveRight(); void Joy_MoveLeftStop(); void Joy_MoveRightStop();

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

#ifndef JOYSTICK_H #define JOYSTICK_H #include #include #include #include class JoyStick; /** * @brief The JoyStickThread class * @details 内部类,定时轮询 JoyStick 的状态。 */ class JoyStickThread : public QThread { public: explicit JoyStickThread(); void setJoyStick(JoyStick *joystick); void run(); void stop(); private: void Coordinate_StateMachine(int xPos, int yPos); void AxisX_StateMachine(int xPos); void AxisY_StateMachine(int yPos); void Button_StateMachine(int button); void POV_StateMachine_Axis(int pov); void POV_StateMachine(int pov); int old_xPos; int old_yPos; int old_pov; bool pov_forward; bool pov_backward; bool pov_left; bool pov_right; bool pov_center; int m_button[16]; JoyStick *m_joystick; bool m_run; }; class JoyStick : public QObject { Q_OBJECT public: enum MODE{SWITCH_MODE, COORDINATE_MODE}; /** * @brief JoyStick * @param mode SWITCH_MODE 模式时,摇杆输出开关量。COORDINATE_MODE 模式时,输出摇杆的位置。 * @param parent */ explicit JoyStick(enum MODE mode = SWITCH_MODE, QObject *parent = 0); enum MODE mode() const {return m_mode;} ~JoyStick(); /** * @brief listen * @return 启动监听线程,之后就可以接收手柄的各种消息了。 */ bool listen(); /** * @brief stop 停止监听线程,不需要接收手柄消息时可以调用这个函数。 */ void stop(); signals: /// JoyStick 的摇杆的各种信号。 /// 高级些的手柄是可以返回摇杆的坐标值的。 /// 这里模仿的是工业摇杆,输出的都是开关量。 /// 前后左右四组开关量。 void Joy_MoveForward(); void Joy_MoveBackward(); void Joy_MoveForwardStop(); void Joy_MoveBackwardStop(); void Joy_MoveLeft(); void Joy_MoveRight(); void Joy_MoveLeftStop(); void Joy_MoveRightStop(); /// JoyStick 的摇杆位置。 void Joy_Position(int x, int y); /** * @brief Joy_ButtonPressed 当手柄上某个按键被按下时发出这个信号 * @param i 用来标志是哪个按键被按下了。 */ void Joy_ButtonPressed(int i); /** * @brief Joy_ButtonReleased 当手柄上某个按键被释放时发出这个信号 * @param i 用来标志是哪个按键被释放了。 */ void Joy_ButtonReleased(int i); /// 以下是视觉头盔的各种信号 void Joy_POVForward(); void Joy_POVBackward(); void Joy_POVLeft(); void Joy_POVRight(); void Joy_POVForwardLeft(); void Joy_POVForwardRight(); void Joy_POVBackwardLeft(); void Joy_POVBackwardRight(); /** * @brief Joy_POVCentered 当视觉头盔从前8种状态恢复到默认状态时发出这个信号。 */ void Joy_POVCentered(); private: enum MODE m_mode; bool m_valid; JoyStickThread m_thread; }; #endif // JOYSTICK_H

下面是cpp 文件:

#include "joystick.h" #include #include JoyStick::JoyStick(enum MODE mode, QObject *parent) : QObject(parent) { m_mode = mode; m_valid = false; m_thread.setJoyStick(this); JOYINFO joyinfo; if( joyGetNumDevs() > 0 && joyGetPos(JOYSTICKID1, &joyinfo) != JOYERR_UNPLUGGED ) { qDebug() Joy_POVForwardRight(); } if( pov == JOY_POVRIGHT ) { emit m_joystick->Joy_POVRight(); } if( pov == JOY_POVRIGHT + 4500 ) { emit m_joystick->Joy_POVBackwardRight(); } if( pov == JOY_POVBACKWARD ) { emit m_joystick->Joy_POVBackward(); } if( pov == JOY_POVBACKWARD + 4500 ) { emit m_joystick->Joy_POVBackwardLeft(); } if( pov == JOY_POVLEFT ) { emit m_joystick->Joy_POVLeft(); } if( pov == JOY_POVLEFT + 4500 ) { emit m_joystick->Joy_POVForwardLeft(); } if( pov == JOY_POVCENTERED ) { emit m_joystick->Joy_POVCentered(); } old_pov = pov; } } void JoyStickThread::POV_StateMachine_Axis(int pov) { if(pov != old_pov) { //qDebug() Joy_MoveForward(); //qDebug() Joy_MoveLeftStop(); //qDebug() Joy_MoveRightStop(); //qDebug() Joy_MoveForward(); //qDebug() Joy_MoveRight(); //qDebug() Joy_MoveRight(); //qDebug() Joy_MoveForwardStop(); //qDebug() Joy_MoveBackwardStop(); //qDebug() Joy_MoveRight(); // qDebug() Joy_MoveBackward(); // qDebug() Joy_MoveBackward(); //qDebug() Joy_MoveLeftStop(); //qDebug() Joy_MoveRightStop(); //qDebug() Joy_MoveBackward(); //qDebug() Joy_MoveLeft(); // qDebug() Joy_MoveLeft(); //qDebug() Joy_MoveForwardStop(); //qDebug() Joy_MoveBackwardStop(); //qDebug() Joy_MoveLeft(); //qDebug() Joy_MoveForward(); //qDebug() Joy_MoveForwardStop(); //qDebug() Joy_MoveBackwardStop(); //qDebug() Joy_MoveLeftStop(); //qDebug() Joy_MoveRightStop(); //qDebug() Joy_MoveForwardStop(); } else { emit m_joystick->Joy_MoveBackwardStop(); } break; case 65535: emit m_joystick->Joy_MoveBackward(); break; } old_yPos = yPos; }

具体的使用方法很简答,建立对象后,只要调用 listen() 函数开始监听就可以了。 当然在监听之前,还要连接好需要的信号和槽。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3