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

环境工具

系统archlinux

手柄 北通360, usb

安卓手机 小米11

游戏 流行群侠传

步骤

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

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

安装scrcpy

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

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会出现连点的情况

"""
通过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

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

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

说明

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

摇杆目前无法适应

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

posted @ 2022-12-25 20:16  p205  阅读(418)  评论(0编辑  收藏  举报