如何用Python实现双按键同时按住?游戏场景按键交替问题
解决游戏中无法同时按住多键的问题
游戏和普通文本输入的按键监听机制完全不同——多数游戏采用DirectInput或Raw Input直接读取硬件输入状态,而keyboard/pyautogui这类库是通过Windows消息队列模拟按键事件,游戏往往不识别这种“软件层面”的模拟信号,因此会出现按键交替、无法同时按住的情况。以下是两个可行的解决办法:
方法1:用pynput库(简单易实现)
pynput的键盘模拟更贴近底层,对游戏兼容性更好。先安装库:
pip install pynput
替换你的代码为:
import time from pynput.keyboard import Controller import serial keyboard = Controller() # 主循环(替换成你原本的串口读取逻辑) while True: # 示例:读取串口数据,这里替换成你的实际代码 dataPacket = ser.readline() if dataPacket.startswith(b"4"): # 同时按住D和W keyboard.press('d') keyboard.press('w') print("yo1") # 保持按键直到你需要的条件结束,这里用sleep示例,可替换为循环判断 time.sleep(0.1) # 释放按键 keyboard.release('d') keyboard.release('w') if dataPacket.startswith(b"5"): keyboard.press('a') keyboard.press('w') print("yo2") time.sleep(0.1) keyboard.release('a') keyboard.release('w')
如果游戏里的WASD对应方向键,可改用Key.up/Key.left这类枚举值替代字符键。
方法2:用ctypes调用Windows原生SendInput API(最底层,兼容性拉满)
如果pynput仍不生效,直接调用系统API模拟硬件级输入,几乎所有游戏都能识别:
import time import ctypes import serial # 定义Windows API相关结构与函数 user32 = ctypes.WinDLL('user32', use_last_error=True) INPUT_KEYBOARD = 1 KEYEVENTF_KEYUP = 0x0002 class KEYBDINPUT(ctypes.Structure): _fields_ = [("wVk", ctypes.c_ushort), ("wScan", ctypes.c_ushort), ("dwFlags", ctypes.c_ulong), ("time", ctypes.c_ulong), ("dwExtraInfo", ctypes.POINTER(ctypes.c_ulong))] class INPUT(ctypes.Structure): _fields_ = [("type", ctypes.c_ulong), ("ki", KEYBDINPUT)] def press_key(vk_code): input_event = INPUT(type=INPUT_KEYBOARD, ki=KEYBDINPUT(wVk=vk_code, wScan=0, dwFlags=0, time=0, dwExtraInfo=None)) user32.SendInput(1, ctypes.byref(input_event), ctypes.sizeof(input_event)) def release_key(vk_code): input_event = INPUT(type=INPUT_KEYBOARD, ki=KEYBDINPUT(wVk=vk_code, wScan=0, dwFlags=KEYEVENTF_KEYUP, time=0, dwExtraInfo=None)) user32.SendInput(1, ctypes.byref(input_event), ctypes.sizeof(input_event)) # 按键对应的VK码 VK_W = 0x57 VK_A = 0x41 VK_D = 0x44 # 主逻辑 while True: dataPacket = ser.readline() if dataPacket.startswith(b"4"): press_key(VK_D) press_key(VK_W) print("yo1") time.sleep(0.1) release_key(VK_D) release_key(VK_W) if dataPacket.startswith(b"5"): press_key(VK_A) press_key(VK_W) print("yo2") time.sleep(0.1) release_key(VK_A) release_key(VK_W)
额外提示
如果需要保持按键直到某一条件触发(比如串口数据变化),可以把固定的time.sleep(0.1)替换为循环判断逻辑:
# 示例:保持按键直到dataPacket不再以b"4"开头 if dataPacket.startswith(b"4"): press_key(VK_D) press_key(VK_W) print("yo1") while dataPacket.startswith(b"4"): time.sleep(0.01) # 短延时避免CPU占用过高 dataPacket = ser.readline() release_key(VK_D) release_key(VK_W)
内容的提问来源于stack exchange,提问作者Mr Blue
相关产品推荐
相关产品推荐

