我想弄清楚如何在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没有检测到它。