pygame-community / pygame-ce

🐍🎮 pygame - Community Edition is a FOSS Python library for multimedia applications (like games). Built on top of the excellent SDL library.
https://pyga.me
825 stars 131 forks source link

PS4 controller on Raspberry Pi OS detected with legacy mappings #2651

Open celeritydesign opened 8 months ago

celeritydesign commented 8 months ago

pygame-ce 2.4.0 Raspberry Pi OS latest version (running on Raspberry Pi 5 hardware) python 3.11.2

As per docs, a PS4 controller should be recognised by pygame as "PS4 Controller", and does not have any hats (d-pad is read as normal buttons).

On Raspberry Pi OS, it is detected as "Wireless Controller" and exactly matches the note in the docs for pygame 1.x (ref: https://pyga.me/docs/ref/joystick.html )

The difference is that on the Pi, it has a hat, so I have to handle both scenarios in my game, so it works consistently between our Pi and my laptop. If I get a chance, I'll test using a RasPi 4 as well, but that could take me a while.

(note, the above behaviour is seen using three different official Sony controllers and is unchanged in either wired or bluetooth mode)

Assuming this issue can be replicated by others, can it be fixed within the pygame install, or is this a problem with the Raspberry Pi OS distro?

oddbookworm commented 8 months ago

I have a raspi 5 that I’ve been looking for a reason to use. I’ll take a look locally hopefully tonight and see if I can figure out what’s going on

oddbookworm commented 8 months ago

@celeritydesign If you're around, could you tell me which version of raspberry pi OS you've installed? I'm going to install the 64-bit version for now, but if you're using the 32-bit version, that would be potentially useful to know

oddbookworm commented 8 months ago

Here's my results from this test script with my ps4 controller plugged into the usb slot

import pygame

pygame.init()
pygame.joystick.init()

pygame.print_debug_info()

joy = pygame.joystick.Joystick(0)
print(joy.get_name())

output

pygame-ce 2.4.0 (SDL 2.28.5, Python 3.11.2)
Platform:               Linux-6.1.0-rpi7-rpi-2712-aarch64-with-glibc2.36
System:                 Linux
System Version:         #1 SMP PREEMPT Debian 1:6.1.63-1+rpt1 (2023-11-24)
Processor:
Architecture:           Bits: 64bit     Linkage: ELF
Driver:                 x11

Python:                 CPython
pygame version:         2.4.0
python version:         3.11.2

SDL versions:           Linked: 2.28.5  Compiled: 2.28.5
SDL Mixer versions:     Linked: 2.6.3   Compiled: 2.6.3
SDL Font versions:      Linked: 2.20.2  Compiled: 2.20.2
SDL Image versions:     Linked: 2.8.0   Compiled: 2.8.0
Freetype versions:      Linked: 2.13.2  Compiled: 2.13.2
Sony Interactive Entertainment Wireless Controller
oddbookworm commented 8 months ago

I do see that on the pi, the d-pad is indeed a hat. I also noticed another random issue in that the L2 and R2 keys generated two events each. Both each generated a joybuttondown event (probably a joybuttonup too, but I didn't look for those) and a joyaxismotion. On windows, I saw no hats, each d-pad button was a joybuttondown event. L2 and R2 only generated joyaxismotion events

@zoldalma999 any idea what's going on here? I think I remember seeing you messing with controller stuff before, maybe you have an idea?

oddbookworm commented 8 months ago

In the meantime, it's past my bedtime lol. I'll look into this more tomorrow if needed

oddbookworm commented 8 months ago

Before I go, I had a thought. Maybe try using the pygame._sdl2.controller API and see if you get more consistent results? https://pyga.me/docs/ref/sdl2_controller.html

celeritydesign commented 8 months ago

@celeritydesign If you're around, could you tell me which version of raspberry pi OS you've installed? I'm going to install the 64-bit version for now, but if you're using the 32-bit version, that would be potentially useful to know

I'm using the 64bit, same as you. Thank you for confirming my experience, it's appreciated!

Before I go, I had a thought. Maybe try using the pygame._sdl2.controller API and see if you get more consistent results? https://pyga.me/docs/ref/sdl2_controller.html

Cheers, I hadn't even noticed that module. ...but I'd prefer to use the "standard" joystick handling from the pygame docs, especially now I've already coded around the RasPi anomaly. Matliss talks about it here and makes me think it's a rabbit hole I don't really want to venture too far down into :) : https://stackoverflow.com/questions/76616451/how-do-i-utilize-the-pygame-sdl2-controller-module-does-it-even-exist

zoldalma999 commented 8 months ago

Can confirm, I have a different mappings on linux (ubuntu) than on windows (with a wired ps4 controller). Not surprising tho, sadly the joystick module is dependent on OS (and drivers). The same issue was mentioned in #1250.

There is no easy way to workaround this, if you want to still use the joystick module, but you could have an interface where the user can set the buttons and axes themselves (with an image of controller on the screen, that has a highlight on a specific button, and asking for the user to press that button). Or you could keep a set of mappings in your program, and use a specific layout based on the controller's guid/name and os...

... which is exactly what the controller module is trying to do. If you don't mind trying out experimental modules, it is a solution that will abstract away the details of what the specific hardware exposes (which is the reason for this uncertainty) into a layout that looks like the xbox's controller scheme. If you want to check for the left dpad, you can say controller.get_button(pygame.CONTROLLER_DPAP_LEFT), instead of guessing whether the controller has a dpad, or is accessible through the buttons instead. As a plus, using any of the constants will be (roughly) at the same place.

There are some starter docs I wrote a bit ago now here, if you want to try mess with it, and you can also @ me (zoldalma) on the pygame-community discord server as well with any question you have. As a note, since it is experimental, the module is not autoimported with import pygame, but you will have to import pygame._sdl2.controller, and initalise it manually.

celeritydesign commented 8 months ago

Many thanks for this. Apologies, I hadn't realised this issue has been raised before. Stuff that is probably worth doing:

I can certainly help with the first (and maybe check some other controllers too). I'm not familiar with how to commit changes to the docs, but I can look into it if nobody else volunteers :-) .

oddbookworm commented 8 months ago

Interestingly, on Manjaro, the controller behaves exactly like it does on windows (I didn't test the touchpad on windows, but on manjaro it's treated like the mouse)

Update: windows didn't seem to recognize the touchpad on the controller at all as far as I could tell. pygame.joystick.get_count() returned 1 and using the touchpad didn't do anything. It does recognize it as a button when pressed though