0%

用手柄控制 Minecraft

Minecraft Java 版并不支持通过手柄进行游戏,而只能够使用鼠标和键盘,这无疑是令人遗憾的。如果要用手柄玩 Minecraft,有以下几种比较简单的解决方案:

  • 入手基岩版
  • 安装 Controllable mod
  • 使用手柄映射软件
  • 通过硬件方法映射

本文将介绍通过硬件方法映射的步骤。这里用到的硬件包括

  • Arduino Leonardo
  • USB Host Shield

在文章将电键变为鼠标和键盘 —— 实现篇中,笔者正是通过 Arduino Leonardo 模拟了鼠标和键盘。这里也是类似的,通过 Arduino 读取手柄的按键信息,然后转换为对应的鼠标和键盘操作,实现用手柄控制 Minecraft。

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
/*
Example sketch for the Xbox ONE USB library - by guruthree, based on work by
Kristian Lauszus.
*/

#define SENSITIVITY 4

#include <XBOXONE.h>
#include "Keyboard.h"
#include "Mouse.h"

// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#endif
#include <SPI.h>

USB Usb;
XBOXONE Xbox(&Usb);

bool click_d = false;
bool click_a = false;
bool click_w = false;
bool click_s = false;
bool click_shift = false;

void setup() {
Serial.begin(115200);
Mouse.begin();
Keyboard.begin();
//while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
if (Usb.Init() == -1) {
Serial.print(F("\r\nOSC did not start"));
while (1); //halt
}
Serial.print(F("\r\nXBOX USB Library Started"));
}
void loop() {
Usb.Task();
if (Xbox.XboxOneConnected) {
if (Xbox.getAnalogHat(LeftHatX) > 7500 && !click_d) {
Keyboard.press('d');
click_d = true;
}
if (Xbox.getAnalogHat(LeftHatX) < -7500 && !click_a) {
Keyboard.press('a');
click_a = true;
}
else if (Xbox.getAnalogHat(LeftHatX) < 2000 && Xbox.getAnalogHat(LeftHatX) > -2000) {
if (click_d) {
Keyboard.release('d');
click_d = false;
}
if (click_a) {
Keyboard.release('a');
click_a = false;
}
}

if (Xbox.getAnalogHat(LeftHatY) > 7500 && !click_w) {
Keyboard.press('w');
click_w = true;
}
if (Xbox.getAnalogHat(LeftHatY) < -7500 && !click_s) {
Keyboard.press('s');
click_s = true;
}
else if (Xbox.getAnalogHat(LeftHatY) < 2000 && Xbox.getAnalogHat(LeftHatY) > -2000) {
if (click_s) {
Keyboard.release('s');
click_s = false;
}
if (click_w) {
Keyboard.release('w');
click_w = false;
}
}

if (Xbox.getAnalogHat(RightHatX) > 7500) {
// move mouse right
Mouse.move(SENSITIVITY, 0);
}
if (Xbox.getAnalogHat(RightHatX) < -7500) {
// move mouse left
Mouse.move(-SENSITIVITY, 0);
}

if (Xbox.getAnalogHat(RightHatY) > 7500) {
// move mouse up
Mouse.move(0, -SENSITIVITY);
}
if (Xbox.getAnalogHat(RightHatY) < -7500) {
// move mouse down
Mouse.move(0, SENSITIVITY);
}

// Set rumble effect
static uint16_t oldL2Value, oldR2Value;
if (Xbox.getButtonPress(L2) != oldL2Value || Xbox.getButtonPress(R2) != oldR2Value) {
oldL2Value = Xbox.getButtonPress(L2);
oldR2Value = Xbox.getButtonPress(R2);
uint8_t leftRumble = map(oldL2Value, 0, 1023, 0, 255); // Map the trigger values into a byte
uint8_t rightRumble = map(oldR2Value, 0, 1023, 0, 255);
}

if (Xbox.getButtonClick(UP))
Serial.println(F("Up"));
if (Xbox.getButtonClick(DOWN))
Serial.println(F("Down"));
if (Xbox.getButtonClick(LEFT))
Serial.println(F("Left"));
if (Xbox.getButtonClick(RIGHT))
Serial.println(F("Right"));

if (Xbox.getButtonClick(START)) {
Keyboard.press(KEY_ESC);
Keyboard.release(KEY_ESC);
Serial.println(F("Start"));
}
if (Xbox.getButtonClick(BACK))
Serial.println(F("Back"));
if (Xbox.getButtonClick(XBOX))
Serial.println(F("Xbox"));
if (Xbox.getButtonClick(SYNC))
Serial.println(F("Sync"));

if (Xbox.getButtonClick(L1))
Serial.println(F("L1"));
if (Xbox.getButtonClick(R1))
Serial.println(F("R1"));
if (Xbox.getButtonPress(L2) > 768 && !click_shift) {
Keyboard.press(KEY_LEFT_SHIFT);
click_shift = true;
}
else if (Xbox.getButtonPress(L2) < 256 && click_shift) {
Keyboard.release(KEY_LEFT_SHIFT);
click_shift = false;
}
if (Xbox.getButtonClick(R2))
Serial.println(F("R2"));
if (Xbox.getButtonClick(L3))
Serial.println(F("L3"));
if (Xbox.getButtonClick(R3))
Serial.println(F("R3"));

if (Xbox.getButtonPress(A)) {
Keyboard.press(0x20);
Serial.println(F("A"));
} else {
Keyboard.release(0x20);
}
if (Xbox.getButtonClick(B))
Serial.println(F("B"));
if (Xbox.getButtonClick(X)) {
Keyboard.print("/");
delay(200);
Keyboard.println("time set 0");
Serial.println(F("X"));
}
if (Xbox.getButtonClick(Y))
Serial.println(F("Y"));
}
delay(1);
}