摇杆控制器捕获

简介

原本工作需要对接一个球机的操作键盘,奈何厂商一直没做出来,听到键盘的操作描述与街机摇杆相似,刚好手边有一个,就先写一个Demo尝试一下。

实现方式

手头的摇杆型号为:拳霸 Q1W,接入方式为 xbox360 驱动,使用 DirectInput 获取摇杆操作信息。
由于穷,只买了这一种摇杆,所以其他的品牌或型号的按键可能不太匹配,修改前端的判断即可。

核心代码

完整代码查看:GamepadController

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
/// <summary>
/// DirectInput是用于输入设备(包括鼠标,键盘,操纵杆和其他游戏控制器)
/// https://docs.microsoft.com/en-us/previous-versions/windows/desktop/ee418273(v=vs.85)
/// </summary>
public class DirectInputHelper
{
/// <summary>
/// 是否连接控制器
/// </summary>
public bool isGetJoystick = false;

/// <summary>
/// 连接到的控制器
/// </summary>
private Joystick curJoystick;

/// <summary>
/// 控制器状态捕获计时器
/// </summary>
private Timer _timer;

/// <summary>
/// 当前摇杆状态
/// 用于判断两次摇杆差异
/// </summary>
private int[] RockerData;

/// <summary>
/// 当前按键状态
/// 用于判断两次按键差异
/// </summary>
private bool[] ButtonData;

/// <summary>
/// 摇杆变化事件
/// </summary>
public event Action<int[]> RockerChange;

/// <summary>
/// 按钮变化事件
/// </summary>
public event Action<bool[]> ButtonChange;

/// <summary>
/// 连接控制器
/// </summary>
/// <returns></returns>
public bool ConnectGamepad()
{
if (!isGetJoystick && _timer == null)
{
var vDirectInput = new DirectInput();
var allDevices = vDirectInput.GetDevices();
foreach (var item in allDevices)
{
if (item.Type == DeviceType.Gamepad)
{
curJoystick = new Joystick(vDirectInput, item.InstanceGuid);
curJoystick.Acquire();
isGetJoystick = true;
_timer = new Timer(obj => Update());
_timer.Change(0, 1000 / 60);
}
}
}
return isGetJoystick;
}

/// <summary>
/// 断开控制器
/// </summary>
/// <returns></returns>
public void BreakOffGamepad()
{
if (_timer != null)
{
_timer.Dispose();
_timer = null;
}
if (isGetJoystick)
{
isGetJoystick = false;
}
}

/// <summary>
/// 捕获控制器数据
/// </summary>
private void Update()
{
try
{
var joys = curJoystick.GetCurrentState();
// 摇杆
if (RockerData == null || !Enumerable.SequenceEqual(RockerData, joys.PointOfViewControllers))
{
RockerData = joys.PointOfViewControllers;
RockerChange.Invoke(RockerData);
}
// 按钮
if (ButtonData == null || !Enumerable.SequenceEqual(ButtonData, joys.Buttons))
{
ButtonData = joys.Buttons;
ButtonChange.Invoke(ButtonData);
}
}
catch (Exception)
{
BreakOffGamepad();
}
}
}

游戏演示