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

3

6

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

Stingaree answered 4/4, 2013 at 4:57 Comment(6)
Please don't tell me you are doing this because your joystick is half broken.Bengali
@Bengali no haha, I'm making something fully controlled by a joystick so it would be useful for the program to be able to continue when someone unplugs it temporarily.Stingaree
You are out of luck with here I think, since pygame is based on SDL, and SDL does not support dynamically connecting and disconnecting joysticks. But I heard rumors future versions of SDL should support this...Cutlet
@RyanHaining does my answer work?!Transparent
@Transparent I haven't gotten back to my system in the last couple days (finals week) but I'm gonna try it soon. I think I tried something like this already and doing the quit() followed by init() on the joystick module caused some undesirable effectsStingaree
@RyanHaining good luck with your finals, when you get back to this tell us how it goes.Transparent
T
3

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

Tightlipped answered 19/7, 2022 at 7:8 Comment(0)
T
2

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

Transparent answered 12/5, 2013 at 17:12 Comment(4)
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 runningStingaree
works in my code while running, by that I mean in the example linked in the comment I can discon and reconn and all the buttons and do-dads on my xbox pad work on the displays? What's happing with yours? some buttons not working after the restart or just weird behaviour? (how did you finals go?)Transparent
it might just be the way I have everything else set up, or my controller. I get 0's on my axes and unpressed for all buttons over and over. finals went good btw haha thanksStingaree
I'm going to have another look at this then when I get some time, you got the code your working on on github?Transparent
C
2

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!
Chaetopod answered 2/4, 2017 at 20:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.