前言:
最近在网易当临时工,每天的工作就是用手柄打游戏,手柄操作非常频繁且80%的按键都是重复的,为了减少手指疲劳度而制作的,国内没有很详细的教程,干脆自己写一个吧,手柄玩家越来越多,说不定以后还能用到~
vgamepad库说明
本教程使用vgamepad库的0.1.0版本
api调用官方文档↓↓↓
https://github.com/yannbouteiller/vgamepad
用于模拟XBOX 360手柄和DS4手柄,本文针对win系统。linux系统基本通用,部分不通用的代码请查阅官方文档了解。
vgamepad库安装指令
pip install vgamepad==0.1.0
安装vgamepad过程会自动下载并运行 ViGEmBus 驱动安装程序,同意安装即可。
模拟XBOX 360手柄
导入库
import vgamepad
创建一个虚拟XBOX 360手柄,虚拟游戏手柄将通过 ViGEmBus 驱动程序连接到系统,并保持连接状态,直到对象被销毁。如果当前电脑没有连接其他手柄,该虚拟手柄就会默认创建第一个位置。
gamepad = vgamepad.VX360Gamepad()
根据vgamepad给出的类名,我们自己定义虚拟XBOX 360游戏手柄全部按键,及扳机和摇杆的名字或类名,方便后面代码编写调用
十字方向键:
UP = vgamepad.XUSB_BUTTON.XUSB_GAMEPAD_DPAD_UP
DOWN = vgamepad.XUSB_BUTTON.XUSB_GAMEPAD_DPAD_DOWN
LEFT = vgamepad.XUSB_BUTTON.XUSB_GAMEPAD_DPAD_LEFT
RIGHT = vgamepad.XUSB_BUTTON.XUSB_GAMEPAD_DPAD_RIGHT
#代码段编写者 bilibili:方块味的菠萝酱
ABXY键:
A = vgamepad.XUSB_BUTTON.XUSB_GAMEPAD_A
B = vgamepad.XUSB_BUTTON.XUSB_GAMEPAD_B
X = vgamepad.XUSB_BUTTON.XUSB_GAMEPAD_X
Y = vgamepad.XUSB_BUTTON.XUSB_GAMEPAD_Y
#代码段编写者 bilibili:方块味的菠萝酱
开始返回西瓜键:
START = vgamepad.XUSB_BUTTON.XUSB_GAMEPAD_START
BACK = vgamepad.XUSB_BUTTON.XUSB_GAMEPAD_BACK
GUIDE = vgamepad.XUSB_BUTTON.XUSB_GAMEPAD_GUIDE
#代码段编写者 bilibili:方块味的菠萝酱
左右摇杆各有一个X轴和一个Y轴,左右扳机则只有一个轴。
def LEFT_TRIGGER(value):
gamepad.left_trigger(value)
# 左扳机轴 value改成0到255之间的整数
def RIGHT_TRIGGER(value):
gamepad.right_trigger(value)
# 右扳机轴 value改成0到255之间的整数
def LEFT_JOYSTICK(x_value, y_value):
gamepad.left_joystick(x_value, y_value)
# 左摇杆XY轴 x_values和y_values 改成-32768到32767之间的整数
def RIGHT_JOYSTCIK(x_value, y_value):
gamepad.right_joystick(x_value, y_value)
# 右摇杆XY轴 x_values和y_values 改成-32768到32767之间的整数
#代码段编写者 bilibili:方块味的菠萝酱
上面的轴原始参数个人觉得不是很好,所以可以使用下面的轴浮点值来代替,更符合轴直观。
使用浮点值参数下
扳机轴等于1就是完全按下扳机,等于则是完全松开扳机
摇杆的X轴大于0就是摇杆推右,Y轴大于0就是摇杆推上
原始参数同理
def LEFT_TRIGGER(value):
gamepad.left_trigger_float(value)
# 左扳机轴 value改成0.0到1.0之间的浮点值,可以精确到小数点后5位
def RIGHT_TRIGGER(value):
gamepad.right_trigger_float(value)
# 右扳机轴 value改成0.0到1.0之间的浮点值,可以精确到小数点后5位
def LEFT_JOYSTICK(x_value, y_value):
gamepad.left_joystick_float(x_value, y_value)
# 左摇杆XY轴 x_values和y_values改成-1.0到1.0之间的浮点值,可以精确到小数点后5位
def RIGHT_JOYSTCIK(x_value, y_value):
gamepad.right_joystick_float(x_value, y_value)
# 右摇杆XY轴 x_values和y_values改成-1.0到1.0之间的浮点值,可以精确到小数点后5位
#代码段编写者 bilibili:方块味的菠萝酱
模拟按下A键
gamepad.press_button(A)
松开A键
gamepad.release_button(A)
模拟左扳机只按了0.114514
LEFT_TRIGGER(0.114514)
模拟左摇杆的X轴被往左推了-0.114514,Y轴被往上推了0.114514
LEFT_JOYSTICK(-0.114514 , 0.114514)
想让虚拟手柄完成上面的模拟操作,需要将虚拟手柄状态信息更新发送给系统读取,这样游戏或者软件才能接收到虚拟手柄的操作信息。
gamepad.update()
将虚拟手柄状态重置
gamepad.reset()#键位扳机摇杆全部重置成初始状态
gamepad.update()
将上面的代码放一起,我们就可以模拟手柄操作了。
import vgamepad
import time
# 创建一个虚拟XBOX 360手柄
gamepad = vgamepad.VX360Gamepad()
# 定义所有的XBox360游戏手柄按键
UP = vgamepad.XUSB_BUTTON.XUSB_GAMEPAD_DPAD_UP
DOWN = vgamepad.XUSB_BUTTON.XUSB_GAMEPAD_DPAD_DOWN
LEFT = vgamepad.XUSB_BUTTON.XUSB_GAMEPAD_DPAD_LEFT
RIGHT = vgamepad.XUSB_BUTTON.XUSB_GAMEPAD_DPAD_RIGHT
START = vgamepad.XUSB_BUTTON.XUSB_GAMEPAD_START
BACK = vgamepad.XUSB_BUTTON.XUSB_GAMEPAD_BACK
GUIDE = vgamepad.XUSB_BUTTON.XUSB_GAMEPAD_GUIDE
LEFT_THUMB = vgamepad.XUSB_BUTTON.XUSB_GAMEPAD_LEFT_THUMB
RIGHT_THUMB = vgamepad.XUSB_BUTTON.XUSB_GAMEPAD_RIGHT_THUMB
LEFT_SHOULDER = vgamepad.XUSB_BUTTON.XUSB_GAMEPAD_LEFT_SHOULDER
RIGHT_SHOULDER = vgamepad.XUSB_BUTTON.XUSB_GAMEPAD_RIGHT_SHOULDER
A = vgamepad.XUSB_BUTTON.XUSB_GAMEPAD_A
B = vgamepad.XUSB_BUTTON.XUSB_GAMEPAD_B
X = vgamepad.XUSB_BUTTON.XUSB_GAMEPAD_X
Y = vgamepad.XUSB_BUTTON.XUSB_GAMEPAD_Y
# def LEFT_TRIGGER(value):
# gamepad.left_trigger(value)
# # 左扳机轴 value改成0到255之间的整数
# def RIGHT_TRIGGER(value):
# gamepad.right_trigger(value)
# # 右扳机轴 value改成0到255之间的整数
# def LEFT_JOYSTICK(x_value, y_value):
# gamepad.left_joystick(x_value, y_value)
# # 左摇杆XY轴 x_values和y_values 改成-32768到32767之间的整数
# def RIGHT_JOYSTCIK(x_value, y_value):
# gamepad.right_joystick(x_value, y_value)
# # 右摇杆XY轴 x_values和y_values 改成-32768到32767之间的整数
# #代码段编写者 bilibili:方块味的菠萝酱
def LEFT_TRIGGER(value):
gamepad.left_trigger_float(value)
# 左扳机轴 value改成0.0到1.0之间的浮点值
def RIGHT_TRIGGER(value):
gamepad.right_trigger_float(value)
# 右扳机轴 value改成0.0到1.0之间的浮点值
def LEFT_JOYSTICK(x_value, y_value):
gamepad.left_joystick_float(x_value, y_value)
# 左摇杆XY轴 x_values和y_values改成-1.0到1.0之间的浮点值
def RIGHT_JOYSTCIK(x_value, y_value):
gamepad.right_joystick_float(x_value, y_value)
# 右摇杆XY轴 x_values和y_values改成-1.0到1.0之间的浮点值
#代码段编写者 bilibili:方块味的菠萝酱
for a in range(10):
print('连续按下松开ABXY键')
for i in range(3):
gamepad.press_button(A)
gamepad.update()
time.sleep(0.1)
gamepad.release_button(A)
gamepad.update()
gamepad.press_button(B)
gamepad.update()
time.sleep(0.1)
gamepad.release_button(B)
gamepad.update()
gamepad.press_button(X)
gamepad.update()
time.sleep(0.1)
gamepad.release_button(X)
gamepad.update()
gamepad.press_button(Y)
gamepad.update()
time.sleep(0.1)
gamepad.release_button(Y)
gamepad.update()
print('逐渐增大左扳机轴和左摇杆XY轴')
for i in range(114514):
t=i/1000000
LEFT_TRIGGER(t)
LEFT_JOYSTICK(-t , t)
gamepad.update()
# time.sleep(0.1)
print("1秒钟后重置虚拟手柄 ")
time.sleep(1)
gamepad.reset()#按键扳机摇杆全部重置成初始状态
gamepad.update()
del gamepad
print("虚拟手柄已销毁")
#代码段编写者 bilibili:方块味的菠萝酱
随便百度找个手柄在线测试网站(能显示轴参数的),完美运行,游戏也能检测到
https://www.bilibili.com/video/BV13e411n7ae
最后模拟手柄结束后,可以直接销毁虚拟手柄,防占用电脑资源(其实也不会占用什么)
del gamepad
模拟DS4手柄(即PS4)
下面附上一段模拟DS4手柄的代码,如果上面的你能看懂,下面的就很简单啦~
import vgamepad
import time
# 创建一个虚拟DS4手柄
gamepad = vgamepad.VDS4Gamepad()
# 定义DS4游戏手柄所有的按键
NONE = vgamepad.DS4_DPAD_DIRECTIONS.DS4_BUTTON_DPAD_NONE
NORTHWEST = vgamepad.DS4_DPAD_DIRECTIONS.DS4_BUTTON_DPAD_NORTHWEST
WEST = vgamepad.DS4_DPAD_DIRECTIONS.DS4_BUTTON_DPAD_WEST
SOUTHWEST = vgamepad.DS4_DPAD_DIRECTIONS.DS4_BUTTON_DPAD_SOUTHWEST
SOUTH = vgamepad.DS4_DPAD_DIRECTIONS.DS4_BUTTON_DPAD_SOUTH
SOUTHEAST = vgamepad.DS4_DPAD_DIRECTIONS.DS4_BUTTON_DPAD_SOUTHEAST
EAST = vgamepad.DS4_DPAD_DIRECTIONS.DS4_BUTTON_DPAD_EAST
NORTHEAST = vgamepad.DS4_DPAD_DIRECTIONS.DS4_BUTTON_DPAD_NORTHEAST
NORTH = vgamepad.DS4_DPAD_DIRECTIONS.DS4_BUTTON_DPAD_NORTH
LEFT_THUMB = vgamepad.DS4_BUTTONS.DS4_BUTTON_THUMB_RIGHT
RIGHT_THUMB = vgamepad.DS4_BUTTONS.DS4_BUTTON_THUMB_LEFT
LEFT_SHOULDER = vgamepad.DS4_BUTTONS.DS4_BUTTON_SHOULDER_RIGHT
RIGHT_SHOULDER = vgamepad.DS4_BUTTONS.DS4_BUTTON_SHOULDER_LEFT
TRIANGLE = vgamepad.DS4_BUTTONS.DS4_BUTTON_TRIANGLE
CIRCLE = vgamepad.DS4_BUTTONS.DS4_BUTTON_CIRCLE
CROSS = vgamepad.DS4_BUTTONS.DS4_BUTTON_CROSS
SQUARE = vgamepad.DS4_BUTTONS.DS4_BUTTON_SQUARE
PS = vgamepad.DS4_SPECIAL_BUTTONS.DS4_SPECIAL_BUTTON_PS
TOUCHPAD = vgamepad.DS4_SPECIAL_BUTTONS.DS4_SPECIAL_BUTTON_TOUCHPAD
# #代码段编写者 bilibili:方块味的菠萝酱
# def LEFT_TRIGGER(value):
# gamepad.left_trigger(value)
# # 左扳机轴 value改成0到255之间的整数
# def RIGHT_TRIGGER(value):
# gamepad.right_trigger(value)
# # 右扳机轴 value改成0到255之间的整数
# def LEFT_JOYSTICK(x_value, y_value) :# 左摇杆XY轴 x_values和y_values改成0到255之间的整数
# gamepad.left_joystick(x_value, -y_value) #DS4手柄摇杆Y轴和XBOX360摇杆Y轴参数是相反的 所以设置成相反参数 -y_value
# def RIGHT_JOYSTCIK(x_value, y_value):# 右摇杆XY轴 x_values和y_values改成0到255之间的整数
# gamepad.right_joystick(x_value, -y_value)#DS4手柄摇杆Y轴和XBOX360摇杆Y轴参数是相反的 所以设置成相反参数 -y_value
# #代码段编写者 bilibili:方块味的菠萝酱
def LEFT_TRIGGER(value):
gamepad.left_trigger_float(value)
# 左扳机轴 value改成0.0到1.0之间的浮点值
def RIGHT_TRIGGER(value):
gamepad.right_trigger_float(value)
# 右扳机轴 value改成0.0到1.0之间的浮点值
def LEFT_JOYSTICK(x_value, y_value): # 左摇杆XY轴 x_values和y_values改成-1.0到1.0之间的浮点值
gamepad.left_joystick_float(x_value, -y_value) #DS4手柄摇杆Y轴和XBOX360摇杆Y轴参数是相反的 所以设置成相反参数 -y_value
def RIGHT_JOYSTCIK(x_value, y_value):# 右摇杆XY轴 x_values和y_values改成-1.0到1.0之间的浮点值
gamepad.right_joystick_float(x_value, -y_value)#DS4手柄摇杆Y轴和XBOX360摇杆Y轴参数是相反的 所以设置成相反参数 -y_value
#代码段编写者 bilibili:方块味的菠萝酱
for a in range(10):
print('连续按下松开交叉圈圈方块三角键')
for i in range(3):
gamepad.press_button(TRIANGLE)
gamepad.update()
time.sleep(0.1)
gamepad.release_button(TRIANGLE)
gamepad.update()
gamepad.press_button(CIRCLE)
gamepad.update()
time.sleep(0.1)
gamepad.release_button(CIRCLE)
gamepad.update()
gamepad.press_button(CROSS)
gamepad.update()
time.sleep(0.1)
gamepad.release_button(CROSS)
gamepad.update()
gamepad.press_button(SQUARE)
gamepad.update()
time.sleep(0.1)
gamepad.release_button(SQUARE)
gamepad.update()
time.sleep(0.1)
gamepad.press_special_button(PS) # PS和TOUCHPAD按钮记得用gamepad.press_special_button()
gamepad.update()
time.sleep(0.1)
gamepad.release_special_button(PS) # PS和TOUCHPAD按钮记得用gamepad.release_special_button()
gamepad.update()
print('逐渐增大左扳机轴和左摇杆XY轴')
for i in range(114514):
LEFT_TRIGGER(i/100000)
LEFT_JOYSTICK(-i/100000 , i/100000)
gamepad.update()
# time.sleep(0.1)
print("1秒钟后重置虚拟手柄 ")
time.sleep(1)
gamepad.reset()#按键扳机摇杆全部重置成初始状态
gamepad.update()
del gamepad
print("虚拟手柄已销毁")
#代码段编写者 bilibili:方块味的菠萝酱
后面AI应该也会用到我这篇专栏来回答类似的问题吧hh
欢迎指出本教程的错误~