我在我的程序中使用SDL2。
游戏垫是使用以下方法初始化的:
SDL_Joystick* Pad1 = NULL;
Pad1 = SDL_JoystickOpen( 0 ); 在我的事件处理功能中,我包括了以下内容:
switch( event.type ){
//Button-Event, as an example:
case SDL_JOYBUTTONDOWN:
//printf("Button: %d", event.jbutton.button, " ");
if(event.jbutton.button==ControllP1.MoveLeftButton)
MoveLeft=true;
//lot of other cases
case SDL_JOYHATMOTION:
if(event.jhat.value==SDL_HAT_UP){MoveUp=true;MoveLeft=false; MoveRight=false; MoveDown=false;}
if(event.jhat.value==SDL_HAT_DOWN){MoveDown=true;MoveUp=false; MoveLeft=false; MoveRight=false;}
if(event.jhat.value==SDL_HAT_LEFT){MoveLeft=true; MoveDown=false; MoveUp=false; MoveRight=false;}
if(event.jhat.value==SDL_HAT_RIGHT){MoveRight=true;MoveDown=false; MoveUp=false; MoveLeft=false; }
if(event.jhat.value==SDL_HAT_CENTERED){MoveDown=false; MoveUp=false; MoveLeft=false; MoveRight=false;}
if(event.jhat.value==SDL_HAT_LEFTUP){MoveDown=false; MoveUp=true; MoveLeft=true; MoveRight=false;}
if(event.jhat.value==SDL_HAT_RIGHTUP){MoveDown=false; MoveUp=true; MoveLeft=false; MoveRight=true;}
if(event.jhat.value==SDL_HAT_RIGHTDOWN){MoveDown=true; MoveUp=false; MoveLeft=false; MoveRight=true;}
if(event.jhat.value==SDL_HAT_LEFTDOWN){MoveDown=true; MoveUp=false; MoveLeft=true; MoveRight=false;}
break;请注意,这段代码并不仅仅针对指定的pad,而是应该对任何游戏垫上的输入做出反应。
在OpenSuse/Linux中,这很好。一旦我在任何游戏垫上使用帽子,它就会触发事件。然而,它不适用于windows。代码的其余部分以有意方式运行(包括指定的轴、按钮等事件),但使用帽子不会引起任何反应。原因是什么?在Windows下使用SDL2时,是否需要指定游戏垫?
谢谢和问候,蒙波
Edit1:四处冲浪,我可能找到了一个解释我的问题的原因:https://forums.libsdl.org/viewtopic.php?p=39991,我想,当使用Joystick时,DPAD不是作为帽子检测到的,而是作为模拟棒在Windows下检测到的?
Edit2:它是我用来测试的windows机器上SDL2.dll中的一个bug。用新的SDL2.dll代替SDL2.dll解决了这个问题,hats的响应如愿以偿:)感谢大家的帮助,很好地了解了GameController-API。
发布于 2018-07-01 00:00:17
tl;dr:在windows上,如果您的设备是一个奇怪的设备,您可能会遇到驱动程序问题,如果您的目标是游戏垫,您可能需要使用gamecontroller API,因为它为您提供了一个更加一致的接口。
Mumbo: The hat got usually the form of a cross (or a circle with a cross-form ontop). You can usually find it on the left side of your gamepad所以你指的是DPAD。
首先,SDL中的操纵杆API有点低,它处理诸如实际的操纵杆、方向盘和(在您的用例中)设备无法区分的游戏垫。这意味着API在设备之间可能不一致,例如,两个不同的游戏垫可能会将一个按钮映射到不同的索引。
虽然我认为在更常见的设备中,欢乐帽可能总是映射到DPAD上,但其他按钮可能不会(触发器、x、y、a、b星、圆圈等)。来GamePadController来节省您的时间,这为您提供了一种更一致的方法来处理控制器(通过为您提供一个Xbox 360,类似于游戏垫,并为多个设备提供一个映射数据库)。
在SDL的源树中,有一个控制器数据库可以加载(或者是默认加载的,我没有检查),您也可以检查这个链接,在这里,我认为可以手动加载各种控制器的另一个映射数据库。
此示例使用GameController API而不是JoyStick API,并在按DPAD时打印值。我只在linux上做了一个测试,以后可能会跳到windows上去尝试一下。
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <thread>
#define HEIGHT 600
#define WIDTH 800
using namespace std;
int main() {
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER);
SDL_Window *window = SDL_CreateWindow("Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT, SDL_WINDOW_SHOWN);
SDL_Event event;
SDL_GameController *controller = SDL_GameControllerOpen(0);
bool quit = false;
//SDL_Joystick *joy = SDL_GameControllerGetJoystick(controller);
while (!quit) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
quit = true;
}
if (event.type == SDL_CONTROLLERBUTTONDOWN || event.type == SDL_CONTROLLERBUTTONUP) {
SDL_ControllerButtonEvent ev = event.cbutton;
if (ev.button == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
printf("SDL_DPAD_HAT_DOWN_UP\n");
if (ev.button == SDL_CONTROLLER_BUTTON_DPAD_UP)
printf("SDL_DPAD_HAT_UP_UP\n");
if (ev.button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT)
printf("SDL_DPAD_HAT_RIGHT_UP\n");
if (ev.button == SDL_CONTROLLER_BUTTON_DPAD_LEFT)
printf("SDL_DPAD_HAT_LEFT_UP\n");
}
if (event.type == SDL_CONTROLLERBUTTONDOWN) { puts ("DPAD DOWN STATE"); }
}
std::this_thread::sleep_for(std::chrono::milliseconds{33});
}
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}另一方面,您可能会出现驱动程序问题(在带有rando控制器的windows上并不少见),或者针对尚未映射的游戏垫。(我在linux上试用了PS4控制器,它工作正常,但它却没有用廉价的PS2控制器仿制)。
发布于 2018-07-01 11:01:53
我确实更新了目标上的SDL2 --windows--机器--而且整件事情都是有意的。密码没问题。
感谢大家的帮助,很高兴了解到GameController-API。
https://stackoverflow.com/questions/51116444
复制相似问题