cpp-使用Windows时SDL_JOYHATMOTION是否有所不同?

时间:2018-06-30 16:02:02

标签: c++ windows events sdl gamepad

我在程序中使用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;

请注意,此代码并非仅针对指定的游戏板,而是应对任何游戏板上的输入做出反应。

在OpenSuse / Linux中,这很好。只要在任何游戏手柄上使用帽子,它就会触发该事件。但是,它不适用于Windows。代码的其余部分按预期运行(包括指定的轴,按钮等事件),但是使用Hat不会引起任何反应。这是什么原因呢?在Windows下使用SDL2时需要指定游戏手柄吗?

感谢和问候,小提示

编辑1: 冲浪周围,我可能确实找到了我的问题的解释: https://forums.libsdl.org/viewtopic.php?p=39991 我想在使用Joystick-API时,不是将DPAD检测为HAT,而是检测为Windows下的Analog-Stick吗?

Edit2: 这是我用于测试的Windows计算机上的SDL2.dll中的错误。用新的替换SDL2.dll解决了问题,帽子按预期响应:) 感谢您的帮助,非常了解GameController-API。

2 个答案:

答案 0 :(得分:1)

我确实在目标Windows机器上更新了SDL2-整个工作都按预期进行。代码很好。

感谢任何人的帮助,很高兴了解GameController-API。

答案 1 :(得分:0)

tl; dr:在Windows上,如果您的设备很奇怪,则可能会遇到驱动程序问题;如果要定位游戏手柄,则可能要使用gamecontroller API,因为它为您提供了更一致的使用界面。 / p>

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级别较低,可以处理无法与设备区分的实际joysticks,方向盘和(在您使用的情况下)游戏手柄之类的东西。这意味着API可能在设备之间不一致,例如,两个不同的游戏手柄可能会将按钮映射到不同的索引。

尽管我认为游戏帽可能总是在更常见的设备中映射到DPAD,但其他按钮可能没有(触发,x,y,a,b星,圆等)。快来GamePadController节省一天的时间,这将为您提供一种更一致的方式处理控制器(通过为您提供Xbox 360之类的游戏手柄和多个设备的映射数据库)。

在SDL的源代码树中,有一个数据库可以加载(或默认情况下加载,我没有检查),您也可以在link上检查一下,我认为还有另一个数据库您可以手动加载到程序中的各种控制器的映射。

此示例使用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控制器却没有)。