Game controller button number incompability between SDL2 and other tools (Windows' and online tools)

huangapple go评论59阅读模式
英文:

Game controller button number incompability between SDL2 and other tools (Windows' and online tools)

问题

我尝试在物理游戏控制器设备和虚拟设备(vJoy)之间建立一对一映射。我想要实现的是当按下物理设备上的按钮X时,在虚拟设备上也按下按钮X。

由于我试图在物理和虚拟控制器按钮和轴之间建立一对一映射,我不应该涉及到任何映射。所以我决定使用SDL2库的“Joystick”相关函数,而不是“GameController”相关函数。

输入(物理)=> 我的应用 => 输出(vJoy)

我几乎可以实现对所有控制器的一对一对应,除了一个PS4控制器。

通过SDL输入读取函数(下面是代码),我得到了以下结果:

当我按下左肩按钮时,event.jbutton.button 的值为9

当我按下右肩按钮时,event.jbutton.button 的值为10

在游戏控制器模式下也是9和10,而不是摇杆模式,一样的结果。我确认我没有错误地使用了控制器模式,因为我在不更改任何内容的情况下尝试了同样的方法来测试其他控制器

SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_EVENTS);
SDL_JoystickEventState(SDL_ENABLE);
SDL_Event event;

while(SDL_WaitEventTimeout(&event, 50))
{
    switch(event.type){
        case SDL_JOYDEVICEADDED:
              m_Joystick = SDL_JoystickOpen(device);
        break;
        //
       case SDL_JOYBUTTONDOWN:
       case SDL_JOYBUTTONUP:
               qDebug() << "JoystickButton(" << QString(SDL_GameControllerGetStringForButton((SDL_GameControllerButton)event.jbutton.button)) << ")" << event.jbutton.button << " -> " << event.jbutton.state;
      break;

    }
}

但是当我使用其他工具进行测试时,它们将左肩设为4,右肩设为5。

0-) 我的应用情况

左肩按钮 => 9

右肩按钮 => 10

1-) Windows内置游戏控制器实用程序(索引从1开始,导致为4-5)

2-) 来自 https://gamepad-tester.com/ 的结果

3-) 来自 https://greggman.github.io/html5-gamepad-test/ 的结果

由于我使用了与摇杆相关的函数,我期望以原样读取输入,而不进行映射。但是SDL2的结果似乎与其他工具不同。因此:

1 - 我应该怎么做才能读取摇杆输入,以便与其他工具给出相同的结果?

2 - SDL2和我的代码有什么问题?

英文:

I'm trying to make a 1 to 1 mapping between physical game controller device and virtual device (vJoy). What I want to achieve is when button no X is pressed on physical device, make button no X pressed on virtual device.

Since I'm trying to map 1-1 between physical and virtual controller buttons&axes, I shouldn't have any business with mapping. So I decided to use SDL2 library's 'Joystick' related functions instead of 'GameController' related functions.

Input (Physical) => MyApp => Output(vJoy)

I can achieve 1-1 correspondance with almost all of my controllers except one, which is a PS4 controller.

With SDL input read functions(code below), I get these:

When I press press leftshoulder button, event.jbutton.button says 9

When I press press rightshoulder button, event.jbutton.button says 10

(It also says 9 and 10 in game controller mode instead of joystick mode, same. I confirm I'm not mistakenly using controller mode by trying same method with other controllers without changing anything)

SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_EVENTS);
SDL_JoystickEventState(SDL_ENABLE);
SDL_Event event;

while(SDL_WaitEventTimeout(&amp;event, 50))
{
    switch(event.type){
        case SDL_JOYDEVICEADDED:
              m_Joystick = SDL_JoystickOpen(device);
        break;
        //
       case SDL_JOYBUTTONDOWN:
       case SDL_JOYBUTTONUP:
               qDebug() &lt;&lt; &quot;JoystickButton(&quot; &lt;&lt; QString(SDL_GameControllerGetStringForButton((SDL_GameControllerButton)event.jbutton.button)) &lt;&lt; &quot;)&quot; &lt;&lt; event.jbutton.button&lt;&lt; &quot; -&gt; &quot; &lt;&lt; event.jbutton.state;

      break;

    }
}

But when I test it with other tools, they give 4 for leftshoulder and 5 for rightshoulder as button numbers.

0-) My App Case

LeftShoulder button => 9

RightShoulder button => 10

1-) Windows' internal game controller utility (index starts from 1, which makes 4-5)

Game controller button number incompability between SDL2 and other tools (Windows' and online tools)

2-) Result from https://gamepad-tester.com/

Game controller button number incompability between SDL2 and other tools (Windows' and online tools)

3-) Result from https://greggman.github.io/html5-gamepad-test/

Game controller button number incompability between SDL2 and other tools (Windows' and online tools)

Since I'm using Joystick related functions, I expect to read inputs as is, without mapping. But SDL2 result seems different from others. Since

1 - What should I do to read joystick input so that it will give the same result with other tools

2 - What is wrong with SDL2 and my code?

答案1

得分: 3

SDL2试图保护您免受游戏手柄输入的标准化问题。它重新排列按钮以匹配其自己的标准按钮顺序,基于游戏手柄上每个按钮的物理位置。按钮的顺序由SDL_GamepadButton枚举定义。这就是"9"来自的地方,SDL_GAMEPAD_BUTTON_LEFT_SHOUDLER的值为9。在SDL2中,任何正确映射的游戏手柄都会将L1按钮放在索引9处。

游戏手柄API(在线工具使用的)也在做同样的事情。游戏手柄API定义了一个标准游戏手柄,其"左上前按钮"是buttons[4]。在游戏手柄API中,任何正确映射的游戏手柄都会将L1按钮放在索引4处。

您可以相对容易地在SDL2和游戏手柄API按钮之间进行转换,因为它们都基本上定义了相同的标准按钮集。

Windows游戏控制器实用程序(joy.cpl)不尝试重新映射游戏手柄按钮。它使用DirectInput API,根据分配给每个按钮输入的HID使用标识符来选择按钮索引。

综合起来:

DS4 HID使用ID SDL2 游戏手柄API
交叉 按钮2 SDL_GAMEPAD_BUTTON_A(0) buttons[0]
圆圈 按钮3 SDL_GAMEPAD_BUTTON_B(1) buttons[1]
正方形 按钮1 SDL_GAMEPAD_BUTTON_X(2) buttons[2]
三角形 按钮4 SDL_GAMEPAD_BUTTON_Y(3) buttons[3]
共享 按钮9 SDL_GAMEPAD_BUTTON_BACK(4) buttons[8]
PS 按钮13 SDL_GAMEPAD_BUTTON_GUIDE(5) buttons[16]
选项 按钮10 SDL_GAMEPAD_BUTTON_START(6) buttons[9]
L3 按钮11 SDL_GAMEPAD_BUTTON_LEFT_STICK(7) buttons[10]
R3 按钮12 SDL_GAMEPAD_BUTTON_RIGHT_STICK(8) buttons[11]
L1 按钮5 SDL_GAMEPAD_BUTTON_LEFT_SHOULDER(9) buttons[4]
R1 按钮6 SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER(10) buttons[5]
方向键上 通用桌面帽开关 SDL_GAMEPAD_BUTTON_DPAD_UP(11) buttons[12]
方向键下 通用桌面帽开关 SDL_GAMEPAD_BUTTON_DPAD_DOWN(12) buttons[13]
方向键左 通用桌面帽开关 SDL_GAMEPAD_BUTTON_DPAD_LEFT(13) buttons[14]
方向键右 通用桌面帽开关 SDL_GAMEPAD_BUTTON_DPAD_RIGHT(14) buttons[15]
触摸板按钮 按钮14 SDL_GAMEPAD_BUTTON_TOUCHPAD(20) buttons[16](非标准)
左摇杆X 通用桌面X SDL_GAMEPAD_AXIS_LEFTX(0) axes[0]
左摇杆Y 通用桌面Y SDL_GAMEPAD_AXIS_LEFTY(1) axes[1]
右摇杆X 通用桌面Z SDL_GAMEPAD_AXIS_RIGHTX(2) axes[2]
右摇杆Y 通用桌面Rz SDL_GAMEPAD_AXIS_RIGHTY(3) axes[3]
L2扳机 按钮7(数字),通用桌面Rx(模拟) SDL_GAMEPAD_AXIS_LEFT_TRIGGER(4) buttons[6]
R2扳机 按钮8(数字),通用桌面Ry(模拟) SDL_GAMEPAD_AXIS_RIGHT_TRIGGER(5) buttons[7]

由于我使用了与游戏手柄相关的函数,我希望按原样读取输入,不进行映射。

这是"按原样"。SDL2知道DS4输入报告的确切布局,并从报告缓冲区中读取按钮和轴值。没有重新映射,输入始终正确映射。

但SDL2的结果似乎与其他工具不同。

是的,它使用特定于SDL2的标准按钮顺序。

1 - 为了使读取的游戏手柄输入与其他工具的结果相同,我应该怎么做?

其他工具都有些许不同。如果您想在SDL2和游戏手柄API之间进行转换,您可以使用上面的表格。

2 - SDL2和我的代码有什么问题吗?

没有问题,游戏手柄只是复杂且标准化较差。

英文:

SDL2 is trying to protect you from poor standardization of gamepad inputs. It reorders buttons to match its own standard button ordering based on the physical location of each button on the gamepad. The ordering is defined by the SDL_GamepadButton enum. That's where "9" comes from, SDL_GAMEPAD_BUTTON_LEFT_SHOUDLER has value 9. In SDL2, any correctly-mapped gamepad will have the L1 button at index 9.

Gamepad API (used by online tools) is doing the same thing. Gamepad API defines a Standard Gamepad which has "Top left front button" as buttons[4]. In Gamepad API, any correctly-mapped gamepad will have the L1 button at index 4.

You can convert between SDL2 and Gamepad API buttons fairly easily because they both define essentially the same set of standard buttons.

The Windows game controller utility (joy.cpl) doesn't try to remap gamepad buttons. It's using DirectInput API, which chooses button indices based on the HID usage identifier assigned to each button input.

Putting it all together:

DS4 HID usage ID(s) SDL2 Gamepad API
Cross Button 2 SDL_GAMEPAD_BUTTON_A (0) buttons[0]
Circle Button 3 SDL_GAMEPAD_BUTTON_B (1) buttons[1]
Square Button 1 SDL_GAMEPAD_BUTTON_X (2) buttons[2]
Triangle Button 4 SDL_GAMEPAD_BUTTON_Y (3) buttons[3]
Share Button 9 SDL_GAMEPAD_BUTTON_BACK (4) buttons[8]
PS Button 13 SDL_GAMEPAD_BUTTON_GUIDE (5) buttons[16]
Options Button 10 SDL_GAMEPAD_BUTTON_START (6) buttons[9]
L3 Button 11 SDL_GAMEPAD_BUTTON_LEFT_STICK (7) buttons[10]
R3 Button 12 SDL_GAMEPAD_BUTTON_RIGHT_STICK (8) buttons[11]
L1 Button 5 SDL_GAMEPAD_BUTTON_LEFT_SHOULDER (9) buttons[4]
R1 Button 6 SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER (10) buttons[5]
D-pad Up Generic Desktop Hat Switch SDL_GAMEPAD_BUTTON_DPAD_UP (11) buttons[12]
D-pad Down Generic Desktop Hat Switch SDL_GAMEPAD_BUTTON_DPAD_DOWN (12) buttons[13]
D-pad Left Generic Desktop Hat Switch SDL_GAMEPAD_BUTTON_DPAD_LEFT (13) buttons[14]
D-pad Right Generic Desktop Hat Switch SDL_GAMEPAD_BUTTON_DPAD_RIGHT (14) buttons[15]
Touchpad button Button 14 SDL_GAMEPAD_BUTTON_TOUCHPAD (20) buttons[16] (non-standard)
Left stick X Generic Desktop X SDL_GAMEPAD_AXIS_LEFTX (0) axes[0]
Left stick Y Generic Desktop Y SDL_GAMEPAD_AXIS_LEFTY (1) axes[1]
Right stick X Generic Desktop Z SDL_GAMEPAD_AXIS_RIGHTX (2) axes[2]
Right stick Y Generic Desktop Rz SDL_GAMEPAD_AXIS_RIGHTY (3) axes[3]
L2 trigger Button 7 (digital), Generic Desktop Rx (analog) SDL_GAMEPAD_AXIS_LEFT_TRIGGER (4) buttons[6]
R2 trigger Button 8 (digital), Generic Desktop Ry (analog) SDL_GAMEPAD_AXIS_RIGHT_TRIGGER (5) buttons[7]

> Since I'm using Joystick related functions, I expect to read inputs as is, without mapping.

This is "as-is". SDL2 knows the exact layout of the DS4 input report and reads button and axis values out of the report buffer. There's no remapping happening, the inputs are always correctly mapped.

> But SDL2 result seems different from others.

Yes, it uses a standard button ordering that's specific to SDL2.

> 1 - What should I do to read joystick input so that it will give the same result with other tools

Which other tools? They all are slightly different. If you want to convert between SDL2 and Gamepad API you can use the table above.

> 2 - What is wrong with SDL2 and my code?

Nothing, gamepads are just complicated and poorly standardized.

huangapple
  • 本文由 发表于 2023年5月21日 02:17:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/76296734.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定