SDL_Jostick отправляет странные целые числа

У меня возникли проблемы с использованием SDL (версия 2.0.3) для работы с несколькими игровыми контроллерами в программе SDL/OpenGL/C++.

Я обновляю события с помощью цикла SDL_PollEvent(&m_events) и ищу события SDL_JOYBUTTONDOWN (или SDL_JOYBUTTONUP/SDL_JOYAXISMOTION/SDL_HATMOTION) с переключателем(m_events.type). Я хочу использовать значения m_events.jbutton.what и m_events.jbutton.button (или эквиваленты для осей и шляпы) для обновления массивов, содержащих состояние моих контроллеров.

Я использую Windows 7 Pro 64bit и Code::Blocks 13.12, хотя это ничего не меняет.

Вот мой (отладочный) код, я пытался сохранить только соответствующие части:

main.cpp

#include "SceneOpenGL.h"
int main(int argc, char *argv[])
{
  SceneOpenGL scene(/* some args for window size */);

  if(!scene.initWindow())
    return -1;

  scene.mainLoop();

  return 0;
}

СценаOpenGL.h

#ifndef SCENEOPENGL_H_INCLUDED
#define SCENEOPENGL_H_INCLUDED
#include <iostream>
#include "Input.h"
#include <SDL2/SDL.h>

class SceneOpenGL
{
public:
  SceneOpenGL(/* some args for window size */);
  ~SceneOpenGL();
  bool initWindow();
  void mainLoop();

private:
  SDL_Window* m_window;
  SDL_Event m_event;
  Input m_input;
  bool m_useJoysticks;
};
#endif

СценаOpenGL.cpp

SceneOpenGL::SceneOpenGL(/* some args for window size */) :
  m_window(0), m_input()
{
  if(SDL_NumJoysticks())
    m_useJoysticks = true;
}

bool SceneOpenGL::initWindow()
{
  if(SDL_Init( SDL_INIT_VIDEO | SDL_INIT_JOYSTICK ) == -1)
  {
    std::cout << "Error while initializing SDL : " << SDL_GetError() << std::endl;
    SDL_Quit();
    return false;
  }
  /*
  **** Creation of SDL Window and GLContext ****
  */
  return true;
}

void SceneOpenGL::mainLoop()
{
  if(m_useJoysticks)
  {
    m_input.openJoysticks();
    SDL_JoystickEventState(SDL_ENABLE);
  }

  while(!m_input.terminate()) // m_input.terminate() sends true when SDL receives SDL_WINDOWEVENT_CLOSE event
  {
    m_input.updateEvents(); // this is the other loop where I update the joystick, keyboard & mouse state

    /* ...
    **** moving opengl objects & render ****
    */
  }
}

Вход.ч

#ifndef INPUT_H_INCLUDED
#define INPUT_H_INCLUDED
#include <SDL2/SDL.h>
#include <iostream>

class Input
{
public:
  Input();
  ~Input();
  void updateEvents();
  bool terminate() const;

  void openJoysticks();

private:
  SDL_Event m_events;

  int m_numJoysticks;
  SDL_Joysticks* m_joysticks[4]; // Array containing the first 4 joysicks

  bool m_terminate; // used for ending program
};

Ввод.cpp

#include "Input.h"

Input::Input() :
  m_numJoysticks(0), m_terminate(false)
{}

Input::~Input()
{
  for(int i(0); i < SDL_NumJoysticks(); i++)
    SDL_JoystickClose(m_joysticks[i]); // Closes joysticks before exiting
}

void Input::openJoysticks()
{
  m_numJoysticks = SDL_NumJoysticks; // Counts the connected joysticks
  if(m_numJoysticks > 4)
    m_numJoysticks = 4; // Sets maximum joysticks to 4

  for(int i(0); i < m_numJoysticks; i++)
  {
    m_joysticks[i] = SDL_JoystickOpen(0) // Open existing joysticks
    std::cout << "Joystick #" << i << " OK" << std::endl;
  }
}

void Input::updateEvents()
{
  while(SDL_PollEvent(&m_events))
  {
    switch(m_events.type)
    {
    /* ... Keyboard and mouse events, no problem there */
    case SDL_JOYBUTTONDOWN:
      std::cout << "JOYBUTTONDOWN" << std::endl;
      std::cout << "type : " << m_events.jbutton.type << std::endl;
      std::cout << "which : " << m_events.jbutton.which << std::endl;
      std::cout << "button : " << m_events.jbutton.button << std::endl;
      std::cout << "state : " << m_events.jbutton.state << std:: endl << std::endl;
      break;

    /* ... Same thing for SDL_JOYBUTTONUP, SDL_JOYAXISMOTION, SDL_JOYHATMOTION  */

    case SDL_WINDOWEVENT:
      if(m_events.window.event == SDL_WINDOWEVENT_CLOSE)
        m_terminate = true; // end program
      break;

    default:
      break;
    }
  }
}

bool Input::terminate() const
{
  return m_terminate;
}

Итак, вот вывод консоли, когда я нажимаю A, B, X, Y на моем контроллере x360 (= кнопки 0, 1, 2 и 3):

Joystick #0 OK
JOYBUTTONDOWN
type : 1539
which : 65536
button : §
state : Ý

JOYBUTTONDOWN
type : 1539
which : 1996554496
button :
state :

JOYBUTTONDOWN
type : 1539
which : 1996554752
button :
state :

JOYBUTTONDOWN
type : 1539
which : 1996555008
button :
state :

Process returned 0 (0x0)   execution time : 7.437 s
Press any key to continue.

Как видите, это не совсем нормально. Я даже иногда получаю разные значения для одного и того же ввода (например, здесь при нажатии первой кнопки), но я заметил, что разница между «какими» значениями составляет 256, так что это не совсем случайно. И значения в основном одинаковы, если я перезапускаю программу или дважды нажимаю одну и ту же кнопку. Ну, похоже, что «event.jbutton.what» содержит информацию об индексе кнопки (который должен быть Uint8)

Я не знаю, то ли я делаю это неправильно, то ли это ошибка в SDL2.


person Klowx    schedule 13.10.2014    source источник
comment
на другой платформе работает? Вы пробовали последний источник hg?   -  person Brad Allred    schedule 13.10.2014
comment
похоже, действительно была проблема с исходниками, так что проблема связана с моей установкой.   -  person Klowx    schedule 13.10.2014


Ответы (1)


Ваши числа кажутся побитовым ИЛИ различных полей флагов, возможно, с полем значения.

Изучение их в шестнадцатеричном виде сделает это очевидным:

1996554752 = 0x77010200

1996554496 = 0x77010100

1996555008 = 0x77010300

Похоже, ваш «номер кнопки» может быть в битах 15-8, то есть значения 2, 1, 3

Это почти наверняка описано в соответствующей документации.

person Chris Stratton    schedule 13.10.2014
comment
ну, в документации говорится, что поле SDL_JoyButtonEvent, которое должно быть SDLJoystickID, тогда как значение кнопки должно быть Uint8, хранящимся в другом поле (например, event.jbutton.button) - person Klowx; 13.10.2014
comment
Я хочу сказать, что сам может иметь подполя, в которых разные биты имеют разное назначение. Или у вас может быть несовместимость между фактической библиотекой и вашим заголовком, например, другая упаковка структуры. - person Chris Stratton; 13.10.2014
comment
Второе предположение было действительно правильным (несовместимость между заголовком и библиотекой). Я переустановил версию библиотеки 2.0 (которую я использовал до 2.0.3), и теперь она работает (хотя мне нужно ее дополнительно протестировать). Возможно, я сделал что-то не так при обновлении библиотеки в какой-то момент. - person Klowx; 13.10.2014