pygame: detect Joystick disconnect, and wait for it to be reconnected

Question:

I’m using a pygame.joystick.Joystick object and want to be able to print a message asking the user to reconnect a usb joystick once it’s been unplugged.

right now I have (roughly):

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()

but it doesn’t reconnect properly, idk what exactly it’s doing, but it’s definitely wrong. Any direction on this would be helpful

Asked By: Ryan Haining

||

Answers:

Had to fire up the old xbox pad but I made a function that checks for disconnections and seems to work ok:

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

So if you run this function in your main loop it’ll just keep running itself until it gets a joystick connection back. It works for the little test code I found:

http://programarcadegames.com/python_examples/show_file.php?file=joystick_calls.py

Also found:

http://demolishun.net/?p=21

Where I stole the idea from, he didn’t have any code examples which was lame

And lastly, because you should always check the docs:

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

Answered By: Noelkd

I managed to get mine working with Noelkd’s suggestion, but I had a similar issue described by Ryan Haining

I had something like this at first, but it doesn’t work because the it loses track of the gamepads actions with all the quiting and initing. This works initially to check if a controller is plugged in at all, but not to effectively check while running

I had this issue too. I think you are correct, calling quit too often doesn’t give the pad enough time to re-initialise – at least on my computer. I found that if you limit the calls to every second, it works.

It can cause the player input to temporarily disconnect though, so any calls on a joystick won’t work.

It’s better to only run this code if you detect that there has been no input for a while (say 5 seconds or something). This way you won’t quit while a user is actually using the device

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

Usage

# ... 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!
Answered By: AlexMorley-Finch

Here is pygame events for device add and remove.

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

Answered By: Rahul
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.