You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Win11下GitBash/CMD中Python游戏脚本无法接收键盘输入求助

修复Win11终端下无法接收键盘输入的问题

问题根源

你的脚本使用pynput库监听键盘事件,但在Win11的CMD/GitBash环境中,pynput的全局监听机制容易被Retro游戏窗口抢占焦点,且终端环境的权限限制也会导致事件捕获失败。以下是几种可行的修复方案:


方案一:快速临时修复(无需改代码)

  • 以管理员身份运行终端:右键点击CMD或GitBash,选择「以管理员身份运行」,全局键盘监听需要系统权限。
  • 手动切换焦点:启动脚本后,先点击终端窗口获取焦点,再按下快捷键(Retro游戏窗口启动后会自动抢焦点,需要手动切回终端)。

方案二:替换为终端友好的键盘库(推荐)

pynput替换为更适配终端环境的keyboard库,该库专门针对终端输入优化:

  1. 安装依赖:
pip install keyboard
  1. 修改代码中的键盘监听逻辑,替换原有的pynput相关代码:
# 替换原来的from pynput import keyboard为:
import keyboard

# 在run()方法中,替换原来的on_press、on_release和listener部分:
def run(self):
    print("🕹️ KUNG FU MASTER TRAINER CONTROLS:")
    print("↑ ↓ ← → : Move/Jump/Duck")
    print("A: Punch | S: Kick")
    print("R: Start/Stop recording")
    print("O: Save state | P: Load state")
    print("M: Toggle AI control")
    print("Q: Quit")

    # 按键按下回调
    def on_key_press(e):
        key = e.name.lower()
        if key == 'r':
            self.stop_recording() if self.recording else self.start_recording()
        elif key == 'o':
            self.save_game_state()
        elif key == 'p':
            self.load_game_state()
        elif key == 'm':
            self.toggle_ai()
        elif key == 'q':
            # 退出程序
            keyboard.unhook_all()
            self.env.close()
            exit()
        elif key == 'a':
            self.controls['a'] = True
        elif key == 's':
            self.controls['s'] = True
        elif key == 'up':
            self.controls['up'] = True
        elif key == 'down':
            self.controls['down'] = True
        elif key == 'left':
            self.controls['left'] = True
        elif key == 'right':
            self.controls['right'] = True

    # 按键释放回调
    def on_key_release(e):
        key = e.name.lower()
        if key == 'a':
            self.controls['a'] = False
        elif key == 's':
            self.controls['s'] = False
        elif key == 'up':
            self.controls['up'] = False
        elif key == 'down':
            self.controls['down'] = False
        elif key == 'left':
            self.controls['left'] = False
        elif key == 'right':
            self.controls['right'] = False

    # 注册全局钩子
    keyboard.on_press(on_key_press)
    keyboard.on_release(on_key_release)

    self.env.reset()
    try:
        while True:
            # 原有逻辑保持不变
            if self.ai_playing and self.model:
                frame = self._process_frame(self.env.get_screen())
                action, _ = self.model.predict(frame)
            else:
                action = [
                    int(self.controls['up']),
                    int(self.controls['down']),
                    int(self.controls['left']),
                    int(self.controls['right']),
                    int(self.controls['a']),
                    int(self.controls['s'])
                ]

            obs, _, done, _ = self.env.step(action)

            if self.recording:
                self.current_segment.append((self._process_frame(obs), action))

            self.env.render()
            time.sleep(0.02)

            if done:
                self.env.reset()
    finally:
        keyboard.unhook_all()
        self.env.close()

方案三:优化pynput监听逻辑

如果坚持使用pynput,可以调整监听线程的优先级,并强制终端窗口保持焦点:

  1. 安装额外依赖:
pip install pywin32
  1. 修改run方法中的监听启动代码:
# 在run()方法中,启动listener后添加强制焦点代码:
listener = keyboard.Listener(on_press=on_press, on_release=on_release)
listener.start()

# 强制终端窗口获取焦点
import win32gui
import win32con
win32gui.SetForegroundWindow(win32gui.GetConsoleWindow())

# 原有主循环保持不变

内容的提问来源于stack exchange,提问作者kenpeter

火山引擎 最新活动