python中的虚拟Xbox360和DualShock4游戏手柄
项目描述
虚拟游戏手柄
python中的虚拟Xbox360和DualShock4游戏手柄
Virtual Gamepad ( vgamepad
) 是一个小型 Python 库,可在您的系统上模拟 XBox360 和 DualShock4 游戏手柄。它可以直接从您的 python 脚本控制例如需要模拟输入的视频游戏。
在后台,vgamepad
使用ViGEm C++ 框架,它本质上提供了 python 绑定和用户友好的界面。到目前为止,vgamepad
仅与 Windows 兼容。
快速链接
安装
打开您喜欢的终端(例如 anaconda 提示符)并运行:
pip install vgamepad
这会自动运行 ViGEmBus 驱动程序的安装程序。接受许可协议,单击Install
,允许安装程序修改您的 PC,等待完成并单击Finish
。
vgamepad
现在已安装在您的活动 python 环境中。
入门
vgamepad
提供了两个主要的 python 类:VX360Gamepad
模拟 XBox360 游戏手柄,以及VDS4Gamepad
模拟 DualShock4 游戏手柄。
虚拟游戏手柄的状态(例如按下的按钮、操纵杆值...)称为报告。为了修改报告,由vgamepad
. update
当根据需要修改报告时,必须通过API 功能将其发送到计算机。
Xbox360 游戏手柄
以下 python 脚本创建一个虚拟 Xbox360 游戏手柄:
import vgamepad as vg
gamepad = vg.VX360Gamepad()
一旦VX360Gamepad
创建了对象,虚拟游戏手柄就会通过 ViGEmBus 驱动程序连接到您的系统,并且在对象被销毁之前将保持连接状态。
可以通过press_button
和按下和释放按钮release_button
:
gamepad.press_button(button=vg.XUSB_BUTTON.XUSB_GAMEPAD_A) # press the A button
gamepad.press_button(button=vg.XUSB_BUTTON.XUSB_GAMEPAD_DPAD_LEFT) # press the left hat button
gamepad.update() # send the updated state to the computer
# (...) A and left hat are pressed...
gamepad.release_button(button=vg.XUSB_BUTTON.XUSB_GAMEPAD_A) # release the A button
gamepad.update() # send the updated state to the computer
# (...) left hat is still pressed...
所有可用按钮都定义在XUSB_BUTTON
:
class XUSB_BUTTON(IntFlag):
"""
Possible XUSB report buttons.
"""
XUSB_GAMEPAD_DPAD_UP = 0x0001
XUSB_GAMEPAD_DPAD_DOWN = 0x0002
XUSB_GAMEPAD_DPAD_LEFT = 0x0004
XUSB_GAMEPAD_DPAD_RIGHT = 0x0008
XUSB_GAMEPAD_START = 0x0010
XUSB_GAMEPAD_BACK = 0x0020
XUSB_GAMEPAD_LEFT_THUMB = 0x0040
XUSB_GAMEPAD_RIGHT_THUMB = 0x0080
XUSB_GAMEPAD_LEFT_SHOULDER = 0x0100
XUSB_GAMEPAD_RIGHT_SHOULDER = 0x0200
XUSB_GAMEPAD_GUIDE = 0x0400
XUSB_GAMEPAD_A = 0x1000
XUSB_GAMEPAD_B = 0x2000
XUSB_GAMEPAD_X = 0x4000
XUSB_GAMEPAD_Y = 0x8000
为了控制触发器(每个 1 轴)和操纵杆(每个 2 轴),API 提供了两个选项。
可以直接输入原始整数值:
gamepad.left_trigger(value=100) # value between 0 and 255
gamepad.right_trigger(value=255) # value between 0 and 255
gamepad.left_joystick(x_value=-10000, y_value=0) # values between -32768 and 32767
gamepad.right_joystick(x_value=-32768, y_value=15000) # values between -32768 and 32767
gamepad.update()
或输入浮点值:
gamepad.left_trigger_float(value_float=0.5) # value between 0.0 and 1.0
gamepad.right_trigger_float(value_float=1.0) # value between 0.0 and 1.0
gamepad.left_joystick_float(x_value_float=-0.5, y_value_float=0.0) # values between -1.0 and 1.0
gamepad.right_joystick_float(x_value_float=-1.0, y_value_float=0.8) # values between -1.0 and 1.0
gamepad.update()
重置为默认状态:
gamepad.reset()
gamepad.update()
完整示例:
导入 vgamepad 作为 vg
导入 时间
游戏手柄 = vg 。VX360游戏手柄()
# 按一个按钮唤醒设备
游戏手柄。press_button ( button = vg.XUSB_BUTTON.XUSB_GAMEPAD_A )游戏手柄。_ _ _ 更新()时间。睡眠(0.5 )游戏手柄。release_button ( button = vg.XUSB_BUTTON.XUSB_GAMEPAD_A )游戏手柄。_ _ _ 更新()时间。睡眠( 0.5 )
# 按下按钮和
游戏手柄。press_button ( button = vg.XUSB_BUTTON.XUSB_GAMEPAD_A )游戏手柄。_ _ _ press_button ( button = vg.XUSB_BUTTON.XUSB_GAMEPAD_LEFT_SHOULDER )游戏手柄。_ _ _ press_button ( button = vg.XUSB_BUTTON.XUSB_GAMEPAD_DPAD_DOWN )游戏手柄。_ _ _ press_button ( button = vg . XUSB_BUTTON
. XUSB_GAMEPAD_DPAD_LEFT )
游戏手柄。left_trigger_float ( value_float = 0.5 )
游戏手柄。right_trigger_float ( value_float = 0.5 )
游戏手柄。left_joystick_float ( x_value_float = 0.0 , y_value_float = 0.2 )
游戏手柄。right_joystick_float ( x_value_float =- 1.0 , y_value_float = 1.0 )
游戏手柄。更新()
时间。睡眠( 1.0 )
# 释放按钮和
游戏手柄。release_button ( button = vg.XUSB_BUTTON.XUSB_GAMEPAD_A )游戏手柄。_ _ _ release_button (按钮= vg。XUSB_BUTTON。XUSB_GAMEPAD_DPAD_LEFT )游戏手柄。_ _ _ right_trigger_float ( value_float = 0.0 )游戏手柄。right_joystick_float ( x_value_float = 0.0 , y_value_float = 0.0 )
游戏手柄。更新()
时间。睡眠( 1.0 )
# 将游戏手柄重置为默认状态
gamepad.reset()
gamepad.update()
时间。睡眠( 1.0 )
DualShock4 游戏手柄
使用虚拟 DS4 游戏手柄类似于 X360:
import vgamepad as vg
gamepad = vg.VDS4Gamepad()
按下和释放按钮:
gamepad.press_button(button=vg.DS4_BUTTONS.DS4_BUTTON_TRIANGLE)
gamepad.update()
# (...)
gamepad.release_button(button=vg.DS4_BUTTONS.DS4_BUTTON_TRIANGLE)
gamepad.update()
可用按钮定义在DS4_BUTTONS
:
class DS4_BUTTONS(IntFlag):
"""
DualShock 4 digital buttons
"""
DS4_BUTTON_THUMB_RIGHT = 1 << 15
DS4_BUTTON_THUMB_LEFT = 1 << 14
DS4_BUTTON_OPTIONS = 1 << 13
DS4_BUTTON_SHARE = 1 << 12
DS4_BUTTON_TRIGGER_RIGHT = 1 << 11
DS4_BUTTON_TRIGGER_LEFT = 1 << 10
DS4_BUTTON_SHOULDER_RIGHT = 1 << 9
DS4_BUTTON_SHOULDER_LEFT = 1 << 8
DS4_BUTTON_TRIANGLE = 1 << 7
DS4_BUTTON_CIRCLE = 1 << 6
DS4_BUTTON_CROSS = 1 << 5
DS4_BUTTON_SQUARE = 1 << 4
按下并释放特殊按钮:
gamepad.press_special_button(special_button=vg.DS4_SPECIAL_BUTTONS.DS4_SPECIAL_BUTTON_PS)
gamepad.update()
# (...)
gamepad.release_special_button(special_button=vg.DS4_SPECIAL_BUTTONS.DS4_SPECIAL_BUTTON_PS)
gamepad.update()
特殊按钮定义在DS4_SPECIAL_BUTTONS
:
class DS4_SPECIAL_BUTTONS(IntFlag):
"""
DualShock 4 special buttons
"""
DS4_SPECIAL_BUTTON_PS = 1 << 0
DS4_SPECIAL_BUTTON_TOUCHPAD = 1 << 1
触发器和操纵杆(整数值):
gamepad.left_trigger(value=100) # value between 0 and 255
gamepad.right_trigger(value=255) # value between 0 and 255
gamepad.left_joystick(x_value=0, y_value=128) # value between 0 and 255
gamepad.right_joystick(x_value=0, y_value=255) # value between 0 and 255
gamepad.update()
触发器和操纵杆(浮点值):
gamepad.left_trigger_float(value_float=0.5) # value between 0.0 and 1.0
gamepad.right_trigger_float(value_float=1.0) # value between 0.0 and 1.0
gamepad.left_joystick_float(x_value_float=-0.5, y_value_float=0.0) # values between -1.0 and 1.0
gamepad.right_joystick_float(x_value_float=-1.0, y_value_float=0.8) # values between -1.0 and 1.0
gamepad.update()
- 注意:为了与 X360 API 保持一致,操纵杆上的 Y 轴是倒置的。
方向键(帽子):
gamepad.directional_pad(direction=vg.DS4_DPAD_DIRECTIONS.DS4_BUTTON_DPAD_NORTHWEST)
gamepad.update()
方向键的方向定义在DS4_DPAD_DIRECTIONS
:
class DS4_DPAD_DIRECTIONS(IntEnum):
"""
DualShock 4 directional pad (HAT) values
"""
DS4_BUTTON_DPAD_NONE = 0x8
DS4_BUTTON_DPAD_NORTHWEST = 0x7
DS4_BUTTON_DPAD_WEST = 0x6
DS4_BUTTON_DPAD_SOUTHWEST = 0x5
DS4_BUTTON_DPAD_SOUTH = 0x4
DS4_BUTTON_DPAD_SOUTHEAST = 0x3
DS4_BUTTON_DPAD_EAST = 0x2
DS4_BUTTON_DPAD_NORTHEAST = 0x1
DS4_BUTTON_DPAD_NORTH = 0x0
重置为默认状态:
gamepad.reset()
gamepad.update()
完整示例:
导入 vgamepad 作为 vg
导入 时间
游戏手柄 = vg 。VDS4游戏手柄()
# 按一个按钮唤醒设备
游戏手柄。press_button ( button = vg.DS4_BUTTONS.DS4_BUTTON_TRIANGLE )游戏手柄。_ _ _ 更新()时间。睡眠(0.5 )游戏手柄。release_button ( button = vg.DS4_BUTTONS.DS4_BUTTON_TRIANGLE )游戏手柄。_ _ _ 更新()时间。睡眠( 0.5 )
# 按下按钮和
游戏手柄。press_button ( button = vg.DS4_BUTTONS.DS4_BUTTON_TRIANGLE )游戏手柄。_ _ _ press_button ( button = vg.DS4_BUTTONS.DS4_BUTTON_CIRCLE )游戏手柄。_ _ _ press_button ( button = vg.DS4_BUTTONS.DS4_BUTTON_THUMB_RIGHT )游戏手柄。_ _ _ press_button ( button = vg . DS4_BUTTONS
. DS4_BUTTON_TRIGGER_LEFT )
游戏手柄。press_special_button ( special_button = vg.DS4_SPECIAL_BUTTONS.DS4_SPECIAL_BUTTON_TOUCHPAD )游戏手柄。_ _ _ left_trigger_float ( value_float = 0.5 )游戏手柄。right_trigger_float ( value_float = 0.5 )游戏手柄。left_joystick_float ( x_value_float = 0.0 , y_value_float = 0.2 )游戏手柄
. right_joystick_float ( x_value_float =- 1.0 , y_value_float = 1.0 )
游戏手柄。更新()
时间。睡眠( 1.0 )
# 释放按钮和
游戏手柄。release_button ( button = vg.DS4_BUTTONS.DS4_BUTTON_TRIANGLE )游戏手柄。_ _ _ right_trigger_float ( value_float = 0.0 )游戏手柄。right_joystick_float ( x_value_float = 0.0 , y_value_float = 0.0 )
游戏手柄。更新()
时间。睡眠( 1.0 )
# 将游戏手柄重置为默认状态
gamepad.reset()
gamepad.update()
时间。睡眠( 1.0 )
隆隆声和 LED:
vgamepad
允许注册自定义回调函数来处理震动马达和 LED 环的更新。
自定义回调函数需要 6 个参数:
def my_callback(client, target, large_motor, small_motor, led_number, user_data):
"""
Callback function triggered at each received state change
:param client: vigem bus ID
:param target: vigem device ID
:param large_motor: integer in [0, 255] representing the state of the large motor
:param small_motor: integer in [0, 255] representing the state of the small motor
:param led_number: integer in [0, 255] representing the state of the LED ring
:param user_data: placeholder, do not use
"""
# Do your things here. For instance:
print(f"Received notification for client {client}, target {target}")
print(f"large motor: {large_motor}, small motor: {small_motor}")
print(f"led number: {led_number}")
回调函数需要注册如下:
gamepad.register_notification(callback_function=my_callback)
每次游戏手柄的状态发生变化(例如,通过发送隆隆声请求的视频游戏),回调函数都会被调用。
在我们的示例中,当收到状态更改时,将打印如下内容stdout
:
Received notification for client 2876897124288, target 2876931874736
large motor: 255, small motor: 255
led number: 0
Received notification for client 2876897124288, target 2876931874736
large motor: 0, small motor: 0
led number: 0
如果不再需要,可以取消注册回调函数:
gamepad.unregister_notification()
高级用户:
高级用户可以使用更多的 API 功能,并且可以直接修改报告而不是使用 API。请参阅virtual_gamepad.py。
贡献
欢迎对该项目的所有贡献。请在贡献者列表中提交包含您的姓名和贡献的简短描述的 PR。
作者
维护者:
- 扬·布特勒
贡献者:
- JumpyzZ(隆隆声和 LED)