Pygame:检测手柄断开连接,并等待重新连接

6

我正在使用一个pygame.joystick.Joystick对象,并希望能够打印一条消息,要求用户重新连接USB手柄,一旦手柄被拔掉。

目前我的代码(大致如下):

js = pygame.joystick.Joystick(0)
#... some game code and stuff
pygame.joystick.quit()
pygame.joystick.init()
while pygame.joystick.get_count() == 0:
    print 'please reconnect joystick'
    pygame.joystick.quit()
    pygame.joystick.init()

js = pygame.joystick.Joystick(0)
js.init()

但是它无法正确重新连接,我不知道它到底在做什么,但肯定是错的。对此有任何方向的帮助都将是有益的。


请不要告诉我你这样做是因为你的游戏手柄坏了一半。 - LtWorf
@LtWorf 不,哈哈,我正在制作一些完全由操纵杆控制的东西,因此当某人暂时拔掉它时,程序能够继续运行将非常有用。 - Ryan Haining
我认为你在这里运气不佳,因为pygame基于SDL,而SDL不支持动态连接和断开游戏手柄。但是我听说未来版本的SDL应该会支持这个功能... - sloth
@RyanHaining 我的回答有效吗?! - Noelkd
@Noelkd 我最近几天没能回到我的系统(期末考试周),但我很快会尝试。我想我之前已经尝试过类似的东西,执行游戏手柄模块的 quit() 后跟 init() 会导致一些不良影响。 - Ryan Haining
@RyanHaining,祝你期末考试好运!等你回来后告诉我们考得怎么样。 - Noelkd
3个回答

3

这里是关于设备添加和移除的pygame事件。

joystick = pygame.joystick.Joystick(0)

while True:
    event = pygame.event.wait()

    if event.type == pygame.JOYDEVICEREMOVED:
        joystick.quit()

    elif event.type == pygame.JOYDEVICEADDED:
        joystick.init()

https://www.pygame.org/docs/ref/joystick.html


终于有人解决了! - Ryan Haining

2

我不得不启动旧的Xbox手柄,但我编写了一个检查断开连接的函数,看起来运行良好:

discon = False
def check_pad():
    global discon
    pygame.joystick.quit()
    pygame.joystick.init()
    joystick_count = pygame.joystick.get_count()
    for i in range(joystick_count):
        joystick = pygame.joystick.Joystick(i)
        joystick.init()
    if not joystick_count: 
        if not discon:
           print "reconnect you meat bag"
           discon = True
        clock.tick(20)
        check_pad()
    else:
        discon = False

如果在主循环中运行此函数,它将持续运行直到获得游戏手柄连接。这个小测试代码可以工作:http://programarcadegames.com/python_examples/show_file.php?file=joystick_calls.py。我还从http://demolishun.net/?p=21中找到了灵感,但他没有任何代码示例,这很糟糕。最后,因为你应该总是查看文档:http://www.pygame.org/docs/ref/joystick.html

我一开始也有类似的东西,但它不起作用,因为在所有的“退出”和“初始化”中,它会失去对游戏手柄操作的跟踪。这最初可以用来检查控制器是否已插入,但不能在运行时有效地进行检查。 - Ryan Haining
我的代码在运行时可以正常工作,我指的是在评论中链接的示例中,我可以断开连接并重新连接,我的Xbox手柄上的所有按钮和小玩意都可以在显示器上工作。你的情况怎么样?重启后有些按钮无法工作或者出现奇怪的行为吗?(你期末考试怎么样了?) - Noelkd
1
可能是我设置的方式或者我的控制器有问题。我的轴和所有按钮都一直显示为0和未按下状态。顺便说一句,我的期末考试还不错,哈哈,谢谢。 - Ryan Haining
我稍后会再看一下这个,有时间了你能把你正在github上工作的代码发给我吗? - Noelkd

2
我成功地使用了Noelkd的建议使我的设备工作,但我遇到了Ryan Haining描述的类似问题。
引用: 一开始我也有这样的问题,但是它不能很好地跟踪游戏手柄的操作,因为在所有退出和初始化过程中会失去跟踪。这最初可以检查控制器是否已插入,但不能在运行时有效地检查。
我也遇到了这个问题。我认为你是正确的,过于频繁地调用quit不会给手柄足够的时间重新初始化——至少在我的电脑上是这样。我发现如果你把调用限制在每秒钟一次,它就能工作。
但它会导致玩家输入暂时断开,所以任何关于joystick的调用都将无法工作。
最好只在检测到一段时间内没有输入(比如5秒)时才运行此代码。这样你就不会在用户实际使用设备时退出。
import pygame
import time

INACTIVITY_RECONNECT_TIME = 5
RECONNECT_TIMEOUT = 1

class ControllerInput():
  def __init__(self):
    pygame.joystick.init()
    self.lastTime = 0
    self.lastActive = 0

  def getButtons(self, joystickId):
    joystick = pygame.joystick.Joystick(joystickId)
    joystick.init()

    buttons = {}

    for i in range(joystick.get_numbuttons()):
      buttons[i] = joystick.get_button(i)
      if buttons[i]:
        self.lastActive = time.time()

    return buttons

  def hasController(self):
    now = time.time()
    if now - self.lastActive > INACTIVITY_RECONNECT_TIME and now - self.lastTime > RECONNECT_TIMEOUT:
      self.lastTime = now
      pygame.joystick.quit()
      pygame.joystick.init()

    return pygame.joystick.get_count() > 0

使用方法

# ... some constructor
controller = ControllerInput()

# ... game loop
if not controller.hasController():
  # handle disconnect
  print('reconnect')
  return

buttons = controller.getButtons(0)

if buttons[0]:
  # buttons[0] was pressed!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接