如何测试/处理SDL2游戏控制器输入?

时间:2016-06-28 22:18:11

标签: sdl sdl-2 gamecontroller

我想弄清楚如何在SDL2程序中正确处理游戏控制器输入。我编写了一个程序,它能够处理我Mac上的游戏控制器的输入,但不能在我的Linux机器上处理。但是,游戏控制器可以与Linux机器上的其他程序一起使用。我的程序使用名为Simple2D的库,它包装SDL2以提供更简单的界面。

我正在尝试确定问题是否与Linux端的控制器输入处理或某些缺少的依赖/配置有关。我没有找到任何使用SDL2处理游戏控制器输入以确定代码是否正常工作的示例。

这是Simple2D用于处理游戏控制器输入的代码。你看到任何可能导致我的控制器无法在我的Linux机器上运行的东西吗?

https://github.com/simple2d/simple2d/blob/master/src/simple2d.c#L642-L689

  // Variables for controllers and joysticks
  SDL_GameController *controller = NULL;
  SDL_Joystick *joy = NULL;

  // Enumerate joysticks
  for (int i = 0; i < SDL_NumJoysticks(); ++i) {

    // Check to see if joystick supports SDL's game controller interface
    if (SDL_IsGameController(i)) {
      controller = SDL_GameControllerOpen(i);
      if (controller) {
        sprintf(S2D_msg, "Found a valid controller, named: %s\n",
                SDL_GameControllerName(controller));
        S2D_Log(S2D_msg, S2D_INFO);
        break;  // Break after first available controller
      } else {
        sprintf(S2D_msg, "Could not open game controller %i: %s\n", i, SDL_GetError());
        S2D_Log(S2D_msg, S2D_ERROR);
      }

    // Controller interface not supported, try to open as joystick
    } else {
      sprintf(S2D_msg, "Joystick %i is not supported by the game controller interface", i);
      S2D_Log(S2D_msg, S2D_WARN);
      joy = SDL_JoystickOpen(i);

      // Joystick is valid
      if (joy) {
        sprintf(S2D_msg,
          "Opened Joystick %i\n"
          "Name: %s\n"
          "Axes: %d\n"
          "Buttons: %d\n"
          "Balls: %d\n",
          i, SDL_JoystickName(joy), SDL_JoystickNumAxes(joy),
          SDL_JoystickNumButtons(joy), SDL_JoystickNumBalls(joy)
        );
        S2D_Log(S2D_msg, S2D_INFO);

      // Joystick not valid
      } else {
        sprintf(S2D_msg, "Could not open Joystick %i", i);
        S2D_Log(S2D_msg, S2D_ERROR);
      }

      break;  // Break after first available joystick
    }
  }

https://github.com/simple2d/simple2d/blob/master/src/simple2d.c#L782-L806

SDL_Event e;
while (SDL_PollEvent(&e)) {
  switch (e.type) {

    case SDL_JOYAXISMOTION:
      if (window->on_controller)
        window->on_controller(true, e.jaxis.axis, e.jaxis.value, false, 0);
      break;

    case SDL_JOYBUTTONDOWN:
      if (window->on_controller)
        window->on_controller(false, 0, 0, true, e.jbutton.button);
      break;

更新:感谢@genpfault,我发现SDL代码库附带了一个测试脚本。我正在编译和运行它。下载源代码后,在我的Mac上,我能够成功编译并运行测试脚本,如下所示:

$ cd SDL2-2.0.4/test
$ gcc testgamecontroller.c `sdl2-config --cflags --libs`
$ ./a.out

但是,当我在Linux机器上尝试相同的操作时,它无法编译:

$ gcc testgamecontroller.c `sdl2-config --cflags --libs`
In file included from /usr/include/SDL2/SDL.h:69:0,
                 from testgamecontroller.c:19:
testgamecontroller.c: In function 'main':
testgamecontroller.c:296:132: warning: comparison between pointer and integer
                 SDL_assert(SDL_GameControllerFromInstanceID(SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(gamecontroller))) == gamecontroller);
                                                                                                                                    ^
/usr/include/SDL2/SDL_assert.h:143:19: note: in definition of macro 'SDL_enabled_assert'
         while ( !(condition) ) { \
                   ^
testgamecontroller.c:296:17: note: in expansion of macro 'SDL_assert'
                 SDL_assert(SDL_GameControllerFromInstanceID(SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(gamecontroller))) == gamecontroller);
                 ^
testgamecontroller.c:325:144: warning: comparison between pointer and integer
                             SDL_assert(SDL_GameControllerFromInstanceID(SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(gamecontroller))) == gamecontroller);
                                                                                                                                                ^
/usr/include/SDL2/SDL_assert.h:143:19: note: in definition of macro 'SDL_enabled_assert'
         while ( !(condition) ) { \
                   ^
testgamecontroller.c:325:29: note: in expansion of macro 'SDL_assert'
                             SDL_assert(SDL_GameControllerFromInstanceID(SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(gamecontroller))) == gamecontroller);
                             ^
/tmp/ccipRq1s.o: In function `main':
testgamecontroller.c:(.text+0x8ea): undefined reference to `SDL_GameControllerFromInstanceID'
testgamecontroller.c:(.text+0xa0e): undefined reference to `SDL_GameControllerFromInstanceID'
collect2: error: ld returned 1 exit status

然后我尝试改为运行./configure && make

$ ./configure 
checking build system type... armv7l-unknown-linux-gnueabihf
checking host system type... armv7l-unknown-linux-gnueabihf
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables... 
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking for an ANSI C-conforming const... yes
checking for pkg-config... /usr/bin/pkg-config
checking pkg-config is at least version 0.9.0... yes
checking for SDL... yes
checking how to run the C preprocessor... gcc -E
checking for X... libraries , headers 
checking for OpenGL support... yes
checking for OpenGL ES support... no
checking for OpenGL ES2 support... yes
checking for TTF_Init in -lSDL2_ttf... yes
configure: creating ./config.status
config.status: creating Makefile

$ make
gcc -o checkkeys checkkeys.c -g -O2 -D_REENTRANT -I/usr/include/SDL2  -DHAVE_OPENGLES2 -DHAVE_OPENGL -DHAVE_SDL_TTF -g -lSDL2_test -lSDL2 
gcc -o loopwave loopwave.c -g -O2 -D_REENTRANT -I/usr/include/SDL2  -DHAVE_OPENGLES2 -DHAVE_OPENGL -DHAVE_SDL_TTF -g -lSDL2_test -lSDL2 
gcc -o loopwavequeue loopwavequeue.c -g -O2 -D_REENTRANT -I/usr/include/SDL2  -DHAVE_OPENGLES2 -DHAVE_OPENGL -DHAVE_SDL_TTF -g -lSDL2_test -lSDL2 
/tmp/ccdYXqs4.o: In function `loop':
/home/chip/stash/SDL2-2.0.4/test/loopwavequeue.c:63: undefined reference to `SDL_GetQueuedAudioSize'
/home/chip/stash/SDL2-2.0.4/test/loopwavequeue.c:66: undefined reference to `SDL_QueueAudio'
collect2: error: ld returned 1 exit status
Makefile:78: recipe for target 'loopwavequeue' failed
make: *** [loopwavequeue] Error 1

我不确定为什么它无法编译以及如何移除这些错误。

更新再次感谢@genpfault,从源代码安装最新版本的SDL(2.0.4),而不是使用作为软件包提供的2.0.2版本,修复了我的编译问题

现在当我运行控制器测试脚本时,在我的Linux机器上,我看到了:

2016-06-29 12:59:05.588 a.out[64297:8754739] INFO: There are 0 game controller(s) attached (0 joystick(s))

然而,当我在Mac上运行时,我看到了这一点:

2016-06-29 12:59:25.688 a.out[64303:8755040] INFO: Joystick 0: USB,2-axis 8-button gamepad   (guid 83050000000000006020000000000000)
2016-06-29 12:59:25.690 a.out[64303:8755040] INFO: There are 0 game controller(s) attached (1 joystick(s))

Linux环境有什么不同?同样,同一个控制器可以在同一台Linux机器上的其他程序中运行。

更新:我发现设备已被检测到:

$ cat /proc/bus/input/devices
...

I: Bus=0003 Vendor=0583 Product=2060 Version=0110
N: Name="USB,2-axis 8-button gamepad  "
P: Phys=usb-1c14400.usb-1/input0
S: Sysfs=/devices/platform/soc@01c00000/1c14400.usb/usb2/2-1/2-1:1.0/0003:0583:2060.0003/input/input5
U: Uniq=
H: Handlers=js0 event2 
B: PROP=0
B: EV=1b
B: KEY=ff 0 0 0 0 0 0 0 0 0
B: ABS=3
B: MSC=10

但是,我不确定为什么SDL没有检测到它。

0 个答案:

没有答案