您的位置:首页 > 编程语言

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

2017-09-10 11:21 651 查看

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


分类:
编程杂项(57)




作者同类文章X

版权声明:本文为博主原创文章,未经博主允许不得转载。

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

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

按键对应两个信号:

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



摇杆分为两种模式: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();
1
2
3
4
5
6
7
8



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

void Joy_Position(int x, int y);
1



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

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



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

首先是头文件:

#ifndef JOYSTICK_H
#define JOYSTICK_H

#include <QObject>
#include <QThread>
#include <Windows.h>
#include <Mmsystem.h>

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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113



下面是cpp 文件:

#include "joystick.h"
#include <Windows.h>
#include <QDebug>

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() << "JoyStick Init success!";
m_valid = true;
}
}

JoyStick::~JoyStick()
{
m_thread.stop();
m_thread.wait();
}

bool JoyStick::listen()
{
m_thread.start();
return true;
}
void JoyStick::stop()
{
if(m_thread.isRunning())
{
m_thread.stop();
m_thread.wait();
}
}

JoyStickThread::JoyStickThread()
{
m_run = 1;

old_xPos = 32767;
old_yPos = 32767;
for(int i = 0; i < 16; i++)
{
m_button[i] = 0;
}
old_pov = JOY_POVCENTERED;
pov_forward = false;
pov_backward = false;
pov_left = false;
pov_right = false;
pov_center = true;
}

void JoyStickThread::stop()
{
m_run = 0;
}

void JoyStickThread::setJoyStick(JoyStick *joystick)
{
m_joystick = joystick;
}

void JoyStickThread::run()
{
//JOYINFO joyinfo;
JOYINFOEX joyinfoex;
joyinfoex.dwSize = sizeof(JOYINFOEX);
joyinfoex.dwFlags = JOY_RETURNALL;
while(m_run)
{
//        if(joyGetPos(JOYSTICKID1, &joyinfo) == JOYERR_NOERROR)
//        {
//            //qDebug() << joyinfo.wXpos;
//            AxisX_StateMachine(joyinfo.wXpos);
//            AxisY_StateMachine(joyinfo.wYpos);
//            Button_StateMachine(joyinfo.wButtons);
//        }
if(joyGetPosEx(JOYSTICKID1, &joyinfoex) == JOYERR_NOERROR)
{
if(m_joystick->mode() == JoyStick::SWITCH_MODE)
{
AxisX_StateMachine(joyinfoex.dwXpos);
AxisY_StateMachine(joyinfoex.dwYpos);
}
else
{
Coordinate_StateMachine(joyinfoex.dwXpos, joyinfoex.dwYpos);
}
Button_StateMachine(joyinfoex.dwButtons);
POV_StateMachine_Axis(joyinfoex.dwPOV);
}
msleep(50);
}
}

void JoyStickThread::POV_StateMachine(int pov)
{
if(pov != old_pov)
{
//qDebug() << pov;
if( pov == JOY_POVFORWARD )
{
emit m_joystick->Joy_POVForward();
}
if( pov == JOY_POVFORWARD + 4500 )
{
emit m_joystick->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() << pov;
if( pov == JOY_POVFORWARD )
{
if(pov_forward == false)
{
pov_forward = true;
emit m_joystick->Joy_MoveForward();
//qDebug() << "JOY_POVFORWARD";
}
if(pov_left == true)
{
emit m_joystick->Joy_MoveLeftStop();
//qDebug() << "JOY_POVLEFT RETURN";
}
if(pov_right == true)
{
emit m_joystick->Joy_MoveRightStop();
//qDebug() << "JOY_POVRIGHT RETURN";
}
pov_left = false;
pov_right = false;
}
if( pov == JOY_POVFORWARD + 4500 )
{
if(pov_forward == false)
{
pov_forward = true;
emit m_joystick->Joy_MoveForward();
//qDebug() << "JOY_POVFORWARD";
}
if(pov_right == false)
{
pov_right = true;
emit m_joystick->Joy_MoveRight();
//qDebug() << "JOY_POVRIGHT";
}
}
if( pov == JOY_POVRIGHT )
{
if(pov_right == false)
{
pov_right = true;
emit m_joystick->Joy_MoveRight();
//qDebug() << "JOY_POVRIGHT";
}
if(pov_forward == true)
{
emit m_joystick->Joy_MoveForwardStop();
//qDebug() << "JOY_POVFORWARD RETURN";
}
if(pov_backward == true)
{
emit m_joystick->Joy_MoveBackwardStop();
//qDebug() << "JOY_POVBACKWARD RETURN";
}
pov_forward = false;
pov_backward = false;
}
if( pov == JOY_POVRIGHT  + 4500 )
{
if(pov_right == false)
{
pov_right = true;
emit m_joystick->Joy_MoveRight();
// qDebug() << "JOY_POVRIGHT";
}
if(pov_backward == false)
{
pov_backward = true;
emit m_joystick->Joy_MoveBackward();
// qDebug() << "JOY_POVBACKWARD";
}
}
if( pov == JOY_POVBACKWARD )
{
if(pov_backward == false)
{
pov_backward = true;
emit m_joystick->Joy_MoveBackward();
//qDebug() << "JOY_POVBACKWARD";
}
if(pov_left == true)
{
emit m_joystick->Joy_MoveLeftStop();
//qDebug() << "JOY_POVLEFT RETURN";
}
if(pov_right == true)
{
emit m_joystick->Joy_MoveRightStop();
//qDebug() << "JOY_POVRIGHT RETURN";
}
pov_left = false;
pov_right = false;
}
if( pov == JOY_POVBACKWARD + 4500 )
{
if(pov_backward == false)
{
pov_backward = true;
emit m_joystick->Joy_MoveBackward();
//qDebug() << "JOY_POVBACKWARD";
}
if(pov_left == false)
{
pov_left = true;
emit m_joystick->Joy_MoveLeft();
// qDebug() << "JOY_POVLEFT";
}
}
if( pov == JOY_POVLEFT )
{
if(pov_left == false)
{
pov_left = true;
emit m_joystick->Joy_MoveLeft();
//qDebug() << "JOY_POVLEFT";
}
if(pov_forward == true)
{
emit m_joystick->Joy_MoveForwardStop();
//qDebug() << "JOY_POVFORWARD RETURN";
}
if(pov_backward == true)
{
emit m_joystick->Joy_MoveBackwardStop();
//qDebug() << "JOY_POVBACKWARD RETURN";
}
pov_backward = false;
pov_forward = false;
}
if( pov == JOY_POVLEFT + 4500 )
{
if(pov_left == false)
{
pov_left = true;
emit m_joystick->Joy_MoveLeft();
//qDebug() << "JOY_POVLEFT";
}
if(pov_forward == false)
{
pov_forward = true;
emit m_joystick->Joy_MoveForward();
//qDebug() << "JOY_POVFORWARD";
}
}
if( pov == JOY_POVCENTERED )
{
if(pov_forward == true)
{
emit m_joystick->Joy_MoveForwardStop();
//qDebug() << "JOY_POVFORWARD RETURN";
}
if(pov_backward == true)
{
emit m_joystick->Joy_MoveBackwardStop();
//qDebug() << "JOY_POVBACKWARD RETURN";
}
if(pov_left == true)
{
emit m_joystick->Joy_MoveLeftStop();
//qDebug() << "JOY_POVLEFT RETURN";
}
if(pov_right == true)
{
emit m_joystick->Joy_MoveRightStop();
//qDebug() << "JOY_POVRIGHT RETURN";
}
pov_forward = false;
pov_right = false;
pov_left = false;
pov_backward = false;
//qDebug() << "JOY_POVCENTERED";
}
old_pov = pov;
}
}

void JoyStickThread::Button_StateMachine(int button)
{
//if( button )
//qDebug() << QString::number(button, 16);
const int mask[16] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768};
for(int i = 0; i < 12; i++)
{
int n = button & mask[i];
if(n ^ m_button[i])
{
m_button[i] = n;
if( n )
{
emit m_joystick->Joy_ButtonPressed(i + 1);
//qDebug() << "ButtonPressed(" << i + 1 << ")";
}
else
{
emit m_joystick->Joy_ButtonReleased(i + 1);
//qDebug() << "ButtonReleased(" << i + 1 << ")";;
}
}
}
}

void JoyStickThread::Coordinate_StateMachine(int xPos, int yPos)
{
if(xPos == old_xPos && yPos == old_yPos)
{
return;
}
old_xPos = xPos;
old_yPos = yPos;
emit m_joystick->Joy_Position(xPos, yPos);
}

void JoyStickThread::AxisX_StateMachine(int xPos)
{
if(xPos == old_xPos) return;
switch(xPos)
{
case 0:
emit m_joystick->Joy_MoveLeft();
break;
case 32767:
if(old_xPos == 0)
{
emit m_joystick->Joy_MoveLeftStop();
}
else
{
emit m_joystick->Joy_MoveRightStop();
}
break;
case 65535:
emit m_joystick->Joy_MoveRight();
break;
}
old_xPos = xPos;
}

void JoyStickThread::AxisY_StateMachine(int yPos)
{
if(yPos == old_yPos) return;
switch(yPos)
{
case 0:
emit m_joystick->Joy_MoveForward();
break;
case 32767:
if(old_xPos == 0)
{
emit m_joystick->Joy_MoveForwardStop();
}
else
{
emit m_joystick->Joy_MoveBackwardStop();
}
break;
case 65535:
emit m_joystick->Joy_MoveBackward();
break;
}
old_yPos = yPos;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409



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

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

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++