cpp — SDL_JOYHATMOTION отличается при использовании Windows?

Я использую 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 это нормально. Как только я использую Шляпу на любом Геймпаде, это вызывает событие. Однако это не работает для окон. Остальная часть кода выполняется по назначению (включая указанные события оси, кнопки и т. Д.), Но использование Hat не вызывает никакой реакции. Что является причиной этого? Нужно ли указывать геймпад при использовании SDL2 под Windows?

Спасибо и привет, мамочка

Edit1:
Занимаясь серфингом, я, вероятно, нашел объяснение своей проблемы:
https://forums.libsdl.org/viewtopic.php?p=39991
Я полагаю, что DPAD определяется не как HAT, а как Analog-Stick под Windows при использовании Joystick-API?

Edit2:
Это была ошибка в SDL2.dll на Windows-машине, которую я использовал для тестирования. Замена SDL2.dll на новую решила проблему, шляпы реагируют так, как задумано 🙂
Спасибо за помощь, ребята, приятно узнать о GameController-API.

1

Решение

tl; dr: В Windows у вас могут быть проблемы с драйверами, если ваше устройство странное, и вы можете использовать API-интерфейс gamecontroller, если вы ориентируетесь на игровые планшеты, так как он дает вам более согласованный интерфейс для использования.

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.

Во-первых, API джойстика из SDL немного ниже, обрабатывая такие вещи, как фактический джойстики, рули и (в вашем случае) геймпады неотличимы от устройства. Это означает, что API может быть непоследовательным на разных устройствах, например, две разные игровые панели могут отображать кнопку на разные индексы.

Хотя я думаю, что радости могут всегда отображаться на DPAD в более распространенных устройствах, другие кнопки не могут (триггеры, x, y, a, b звездочка, круг и т. Д.). Приходите к GamePadController, чтобы сэкономить время, что дает вам более последовательный способ управления контроллером (предоставляя вам геймпад, похожий на Xbox 360, и базу данных сопоставлений для нескольких устройств).

В исходном дереве SDL есть база данных контроллеров, которую вы можете загрузить (или загружается по умолчанию, я не проверял), вы также можете проверить это ссылка на сайт где я думаю, что есть другая база данных отображений для всех видов контроллеров, которую вы можете загрузить в свою программу вручную.

В этом примере используется API-интерфейс GameController вместо 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;
}

С другой стороны, у вас могут быть проблемы с ДРАЙВЕРОМ (не редкость в Windows с контроллерами RANDO) или у вас может быть геймпад, который еще не отображен. (Я попробовал Linux с контроллером PS4, и он работал правильно, но с дешевой подделкой контроллера PS2 это не так).

0

Другие решения

Я обновил SDL2 на целевой машине Windows — и все работает так, как задумано. Код в порядке.

Спасибо всем за помощь, приятно узнать о GameController-API.

1

По вопросам рекламы [email protected]