Reputation: 23
I'm using SDL2 in my programm.
The Gamepad is initialised using:
SDL_Joystick* Pad1 = NULL;
Pad1 = SDL_JoystickOpen( 0 );
In my Event-Handling function, i included this thing:
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;
Note that this code isn't targeting only the specified pad but should react to the input on any gamepad.
Within OpenSuse/Linux this is fine. As soon as I use the Hat on any Gamepad, it triggers the event. It however doesn't work for windows. The rest of the Code is running as intented (including the specified axis, button, etc. events) but using the Hat doesn't cause any reaction. What is the reason for this? Do i need to specifiy a gamepad when using SDL2 under Windows?
Thanks and greetings, mumbo
Edit1: Surfing arround, I probably did find an explanation for my problem: https://forums.libsdl.org/viewtopic.php?p=39991 I suppose that the DPAD isn't detected as an HAT but rather as an Analog-Stick under Windows when using the Joystick-API?
Edit2: It was a bug in the SDL2.dll on the windows-machine i used for testing. Replacing the SDL2.dll with the fresh one solved the Problem, hats are responding as intended :) Thanks for the help guys, good to know about the GameController-API.
Upvotes: 1
Views: 731
Reputation: 23
I did update SDL2 on the target-windows-machine - and the whole thing is working as intented. Code is fine.
Thanks for the Help anyone, good to have learned about the GameController-API.
Upvotes: 1
Reputation: 1444
tl;dr: On windows you might be having driver problems if your device is a weird one, and you might want to use the gamecontroller API if you're targeting gamepads as it gives you a more consistent interface to use.
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
So you mean the DPAD.
First, the joystick API from SDL is a bit lower level, handling stuff like actual joysticks, steering wheels and (in your use case) gamepads indistinguishable of the device. This means the API might not be consistent across devices, for example two different gamepads might map a button to different indexes.
Although I think the joyhat might be always mapped to the DPAD in the more common devices, the other buttons might not, (triggers, x, y, a, b star, circle, etc). Come GamePadController to save the day which gives you a more consistent way to handle the controller (by giving you an Xbox 360 like gamepad and a database of mappings for several devices).
In the source tree of SDL there is a databse of controllers you can load (or is loaded by default, I didn't check), you can also check this link where I think there is another database of mappings for all kinds of controllers that you can load into your program by hand.
This example uses the GameController API instead of the JoyStick API and prints values when the DPAD is pressed. I did a test on linux only, might hop on windows later to try it out.
#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;
}
On the other hand you might have DRIVER problems (not uncommon on windows with rando controllers) or be against a gamepad that isn't mapped yet. (I've tried on linux with a PS4 controller and it worked correctly but with a cheap knockoff of a PS2 controller it didn't).
Upvotes: 0