Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Joystick axis  (Read 2433 times)

0 Members and 1 Guest are viewing this topic.

OrHy3

  • Newbie
  • *
  • Posts: 1
    • View Profile
Joystick axis
« on: April 26, 2022, 06:25:56 pm »
I've tried out the Joystick input system with an Xbox Core controller and found out that Z axis is used for both ST and RT buttons (the analogs on the back), while the R axis is unused. Is there a workaround for this? Because I can't determine whether a button is pressed while I'm pressing the other or I'm just releasing one of the buttons (the Z axis return the sum of their position, ST being 0 to 100 and RT being 0 to -100, e.g. value 0 means the analogs are in the same position).
« Last Edit: April 26, 2022, 07:05:22 pm by OrHy3 »

kojack

  • Sr. Member
  • ****
  • Posts: 343
  • C++/C# game dev teacher.
    • View Profile
Re: Joystick axis
« Reply #1 on: April 27, 2022, 02:34:30 am »
Unfortunately this was an intentional design by Microsoft. DirectInput (which SFML uses) merges the analog triggers as a single axis.
From Microsoft's documentation:
Quote
The combination of the left and right triggers in DirectInput is by design. Games have always assumed that DirectInput device axes are centered when there is no user interaction with the device. However, the Xbox controller was designed to register minimum value, not center, when the triggers are not being held. Older games would therefore assume user interaction.

The solution was to combine the triggers, setting one trigger to a positive direction and the other to a negative direction, so no user interaction is indicative to DirectInput of the "control" being at center.


In order to test the trigger values separately, you must use XInput.
Also DirectInput can't do vibration on Xbox controllers, only XInput can.

XInput is incredibly easy to use. But it won't support any controllers that aren't xbox controller compatible (such as flight sim joysticks, play station controllers, etc, which are DirectInput only).

Here's some example code to get the triggers as 0-1 floats:
XINPUT_STATE state;
if(XInputGetState(0,&state) == ERROR_SUCCESS)
{
        float leftTrigger = state.Gamepad.bLeftTrigger / 255.0f;
        float rightTrigger = state.Gamepad.bRightTrigger / 255.0f;
}
 
You don't need to initialise anything, you just ask it for the current state.
Of course as mentioned above, this won't work with non xbox compatible devices, so for wide device support you need multiple methods.