Search code examples
pythonpygletgamepadarcade

Trouble detecting joysticks in Python Arcade (and Pyglet)


I can't seem to get my controllers to detect correctly in using Python Arcade.

I've created a controller object that tests the basic functionality like this:

# tq_menu

class CursorControl():
    joystick_count = len(arcade.get_joysticks())
    def on_step(self):
        if (self.joystick_count != len(arcade.get_joysticks())):
            print("Joystick count changed")
        print(f"Joy count is: {self.joystick_count}")

controller__cursor = CursorControl()

When I first ran it, it seemed to detect when I plugged my controller in. However, after testing it again, I can't get it to work at all.

In my main game code, I have added this for testing:

import tq_menu

class MainGame(arcade.Window):
    def __init__(self):
        super().__init__(600, 600, title="Test Game")
        print("Initial: " + str(arcade.get_game_controllers()))

    def on_update(self, delta_time):
        self.update_tick_count += 1
        if (self.update_tick_count % 60 == 0): self.on_update_second()
    
    def on_update_second(self):
        # Called approx. every second
        print(pyglet.input.get_joysticks())
        print("Before: " + str(arcade.get_game_controllers()))
        print("1 sec")
        tq_menu.controller__cursor.on_step()

I added the direct Pyget function to test... I've used 2 different computers and on my main computer, 3 different controllers (2 wired non-official 360 controllers, 1 wireless Microsoft 360 controller).

In all cases, the arcade.get_joysticks() returns an empty list except for when I initially plug the controller in. The list gets updated and then is empty once more. It is also empty if I run that function on initialisation with a controller plugged in.

My output looks like this (when I plug in):

Initial: []
[]
Before: []
1 sec
Joy count is: 0
[]
Before: []
1 sec
Joy count is: 0
[<pyglet.input.base.Joystick object at 0x000001D677DC9E40>]
Before: []
1 sec
Joy count is: 0
[]
Before: []
1 sec
Joy count is: 0

(The controller remained plugged in and operational after it has been added and dropped from the list.)

I'm really at a loss because I tried the demo code here https://api.arcade.academy/en/latest/examples/sprite_move_joystick.html and still had no joystick detection.

Both my test PCs are running Windows 10 and use Python 3.

Edit:

I created an even more basic test:

import pyglet
import time

while True:
    joysticks = pyglet.input.get_joysticks()
    print(joysticks)
    #time.sleep(0.5)

If I sleep the code, it doesn't register, but if I run it without any sleep, I get this:

[] <- starts empty, although controller is plugged in
[]
[]
[]
[]
[]
[]
[]
[]
[] <- about here I unplug the controller
[]
[]
[]
[]
[]
[<pyglet.input.base.Joystick object at 0x000001F7992877F0>] <- then plug it back in
[]
[]
[]
[]
[]
[] <- then unplug about here
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[<pyglet.input.base.Joystick object at 0x000001F79AD49CF0>] <- re-plug here
[]
[]
[]
[]
[]
[]

Solution

  • A device cannot be DirectInput and be controlled by XInput without possible issues, so it's choosing the XInput as usually it's more compatible, has rumble support, etc.

    You can choose to disable XInput using pyglet.options["xinput_controllers"] = False at the top, after importing pyglet, if you don't want to use it.

    Also to note, 'Joysticks' are technically legacy now with master branch (and Arcade), and in most cases should be replaced with the new controllers API (pyglet.input.get_controllers()). There may be exceptions to this of course, but I would check to see if your devices show up using the new controllers API.

    EDIT: A preview of the new docs can be found here on how it works: https://github.com/pyglet/pyglet/blob/master/doc/programming_guide/input.rst#using-controllers