如何通过电脑手柄玩安卓手机游戏?

环境工具

系统archlinux

手柄 北通360, usb

安卓手机 小米11

游戏 流行群侠传

步骤

手机要打开开发者调试, 并通过usb连接测试

不属于此次重点, 可自行搜索, 通过命令行adb
devices测试输出,说明连接成功

安装scrcpy

此工具用来在电脑端远程操作手机, 并且该软件开源, 而且使用还算流畅

1
sudo pacman -S scrcpy

在手机电脑正常连接的情况下, 直接启动改程序即可

测试键盘控制

通过键盘测试游戏中一些主要操作的对应按键, 后续跟手柄进行绑定

键盘

  1. 前后左右(wsad)

  2. 轻击(h)

  3. 重击(j)

  4. 技能1(u)

  5. 技能2/3(i)

    随从技能也会一起被放出去,真刺激

  6. 闪避(k)

  7. 怒气(p)

  8. 换武器(l)

编写手柄键盘按键映射程序

这里要注意, 按键使用的是keyboard组件, 测试使用pyautogui会出现连点的情况

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
"""
通过python + adb + scrcpy的方式,实现手柄玩安卓手机游戏

# Released by rdb under the Unlicense (unlicense.org)
# Based on information from:
# https://www.kernel.org/doc/Documentation/input/joystick-api.txt

# 参考
https://blog.csdn.net/Enderman_xiaohei/article/details/88050036?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-9-88050036-blog-109139735.pc_relevant_3mothn_strategy_recovery&spm=1001.2101.3001.4242.6&utm_relevant_index=12

https://blog.csdn.net/dhjabc_1/article/details/117444998

使用:
linux下需要使用管理员身份运行(触发按键需要), 否则运行报错

sudo python xx.py

"""
import pygame
# 键盘
import keyboard
import pyautogui
import time

# 鼠标, 没啥用了
# from pymouse import PyMouseMeta
# m = PyMouseMeta()


class JoyToKey:
"""
将手柄映射到键盘输入上
"""

def exec(self, joystick, event):
# 可能的joystick行为: JOYAXISMOTION JOYBALLMOTION JOYBUTTONDOWN JOYBUTTONUP JOYHATMOTION
# if event.type == pygame.JOYBUTTONUP:
# print("Joystick button released.")
# ********************键盘按键********************
if event.type == pygame.KEYDOWN:
# print(pygame.key.get_pressed())
pass
# event.key 表示键盘按键的值,比如k 的值是107, 回车键的值是13,等
# self.toggle_show_fps(event.key)
elif event.type == pygame.KEYUP:
# print(pygame.key.get_pressed())
pass

# ********************手柄操作********************
elif event.type == pygame.JOYBUTTONDOWN:
# 检测到手柄上的键按下
# print("Joystick button pressed.")
if joystick.get_button(7) == 1:
# 手柄start键 --> 键盘中的回车键。
keyboard.press('enter')
if joystick.get_button(0) == 1:
# 手柄A键 --> 键盘的k键,也就是对应跳(闪)的功能。
keyboard.press('k')
if joystick.get_button(2) == 1:
# 手柄X键 --> 键盘u
keyboard.press('u')
if joystick.get_button(1) == 1:
# 手柄B键 --> 键盘i
keyboard.press('i')
if joystick.get_button(3) == 1:
# 手柄Y键 --> 键盘p
keyboard.press('p')
if joystick.get_button(4) == 1:
keyboard.press('h')
if joystick.get_button(5) == 1:
# 手柄又键 --> 键盘l(换武器)
# keyboard.press('l')
keyboard.press('j')
elif event.type == pygame.JOYBUTTONUP:
# print("Joystick button release.")
if joystick.get_button(7) == 0:
# 手柄start键 --> 键盘中的回车键。
keyboard.release('enter')
if joystick.get_button(0) == 0:
# 手柄A键 --> 键盘的k键,也就是对应跳(闪)的功能。
keyboard.release('k')
if joystick.get_button(2) == 0:
# 手柄X键 --> 键盘u
keyboard.release('u')
if joystick.get_button(1) == 0:
# 手柄B键 --> 键盘i
keyboard.release('i')
if joystick.get_button(3) == 0:
# 手柄Y键 --> 键盘p
keyboard.release('p')
if joystick.get_button(4) == 0:
keyboard.release('h')
if joystick.get_button(5) == 0:
# 手柄又键 --> 键盘l(换武器)
# keyboard.release('l')
# 攻击键容易连点
keyboard.release('j')

# 攻击键
elif event.type == pygame.JOYAXISMOTION:
# print("Joystick axis pressed.")
if joystick.get_axis(2) > 0:
# 手柄左x --> 键盘h
# 注意: 这里需要让手柄, pygame来控制按压和释放, 如果用pyautogui, keydown每次会触发很多按压,(连点)
# 还是用这个保险
keyboard.press('h')
if joystick.get_axis(5) > 0:
# 手柄右x --> 键盘j
keyboard.press('j')
if round(joystick.get_axis(1)) < 0:
# 前
keyboard.press('w')
if round(joystick.get_axis(1)) > 0:
# 后
keyboard.press('s')
if round(joystick.get_axis(0)) < 0:
# 左
keyboard.press('a')
if round(joystick.get_axis(0)) > 0:
# 右
keyboard.press('d')

# 释放
# print("Joystick axis released.")
# print("s", joystick.get_axis(1))
if joystick.get_axis(2) < 0:
# 手柄左x --> 键盘h
keyboard.release('h')
if joystick.get_axis(5) < 0:
# 手柄右x --> 键盘j
keyboard.release('j')
if round(joystick.get_axis(0)) == 0:
# 释放左右
keyboard.release('a')
keyboard.release('d')
if round(joystick.get_axis(1)) == 0:
# 释放前后
keyboard.release('w')
keyboard.release('s')

# 摇杆转向
# 当前鼠标光标位置, 固定位置, 不单独获取了
# x, y = pygame.mouse.get_pos()
x, y = 482, 305
pyautogui.moveTo(x, y)
# 1. 设置当前鼠标光标位置, 放中间或偏右
# 2. 根据摇杆变化, 利用pyautogui进行拖拽
# 3, 4为遥感的横/纵向变化
if joystick.get_axis(3) != 0 or joystick.get_axis(4) != 0:
# 将当前光标位置的东西向下移动100个像素点,在拖动的过程中按住鼠标左键。
# >> > pyautogui.drag(100, 0, button='left')
# 一样的问题, 连点
# pyautogui.drag(int(round(joystick.get_axis(4))), int(round(joystick.get_axis(3))), button='left')
print(y+int(round(joystick.get_axis(4))), x+int(round(joystick.get_axis(3))))

# 使用pymouse实现上述payautogui的拖拽
# x, y = pygame.mouse.get_pos()
# m.press(x, y)
# x1 = x + joystick.get_axis(3)
# y1 = y + joystick.get_axis(4)
# m.move(x1, y1)
# m.release(x1, y1)


if __name__ == '__main__':
pygame.init()

# 初始化joystick
pygame.joystick.init()

# 得到joystick的数量
joystick_count = pygame.joystick.get_count()
print("Number of joysticks: {}".format(joystick_count))

# 之考虑一个手柄
joystick = pygame.joystick.Joystick(0)
# 按键映射对象
joyToKey = JoyToKey()

# -------- 程序主循环 -----------
# 保持循环直到用户点击关闭按钮
done = False
while not done:
# 事件处理的步骤
# 手柄事件触发
for event in pygame.event.get():
# 如果用户触发了关闭事件
if event.type == pygame.QUIT:
# 设置我们做了这件事的标志,所以我们就可以退出循环了
done = True
else:
joyToKey.exec(joystick, event)

# 关闭窗口并退出.
pygame.quit()

程序运行

程序使用的是keyboard组件, 在linux下运行时需要sudo

1
sudo python 北通360-流行群侠传手游.py

此时在scrcpy界面, 通过手柄即可控制手机进行游戏操作, 并且流畅性也还可以

说明

只是为了提高下游戏的趣味性, 其它操作可自行发掘

摇杆目前无法适应

摇杆转向跟鼠标适配未实现, 事件刷新太快, 暂时未想到好方法进行转换