Рукоятка управления полетом

На этой странице описаны основы программирования для сертифицированных на Xbox One тестовых палочек с помощью Windows.Gaming.Input.FlightStick и связанных API-интерфейсов для универсальная платформа Windows (UWP).

Прочитав эту страницу, вы узнаете:

  • Как собрать список подключенных устройств и пользователей
  • как определить, что приклека полета была добавлена или удалена
  • как считывать входные данные из одного или нескольких стиков полета
  • Как устройства навигации пользовательского интерфейса ведут себя в качестве устройств навигации по пользовательскому интерфейсу

Обзор

Пролетные наклейки — это игровые входные устройства, которые ценятся для воспроизведения чувства полетных палок, которые будут найдены в самолете или космическом корабле в кабине. Это идеальное устройство ввода для быстрого и точного управления полетом. Тестовые наклейки поддерживаются в приложениях Windows 10 или Windows 11 и Xbox One через пространство имен Windows.Gaming.Input .

Сертифицированные с сертификацией Xbox пролетные наклейки оснащены следующими элементами управления:

  • Кручиваемый аналоговый джойстик, способный рулон, шаг и язь
  • Аналоговый регулирование
  • Две кнопки пожара
  • 8-путь цифрового коммутатора шляпы
  • Кнопки представления и меню

Примечание

Кнопки представления и меню используются для поддержки навигации пользовательского интерфейса, а не команд игрового процесса, поэтому не могут быть легко доступны как кнопки джойстика.

Навигация пользовательского интерфейса

Чтобы облегчить нагрузку на поддержку различных устройств ввода для навигации пользовательского интерфейса и поощрять согласованность между играми и устройствами, большинство физических устройств ввода одновременно действуют в качестве отдельных логических устройств ввода, называемых контроллерами навигации пользовательского интерфейса. Контроллер навигации пользовательского интерфейса предоставляет общий словарь для команд навигации пользовательского интерфейса на устройствах ввода.

В качестве контроллера навигации пользовательского интерфейса с помощью джойстика и кнопки "Вид", "Меню", "FirePrimary" и "FireSecondary" сопоставляются необходимый набор команд навигации.

Команда навигации Входные данные с наклейкой для полета
Up Джойстик вверх
Down Джойстик вниз
Left Джойстик слева
Right Джойстик справа
Представления Кнопка "Просмотреть "
Меню Кнопка меню
Accept Кнопка FirePrimary
Отменить Кнопка FireSecondary

Тестовые наклейки не сопоставляют любой из необязательных наборов команд навигации.

Обнаружение и отслеживание стиков полета

Обнаружение и отслеживание полетных палок работает точно так же, как и для игровых контроллеров, за исключением класса FlightStick вместо класса Gamepad . Дополнительные сведения см. в разделе "Геймпад" и "Вибрация ".

Чтение пролетной палочки

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

Опрос пролетной палки

Опрос захватывает моментальный снимок пролетной палки в точный момент времени. Такой подход к сбору входных данных подходит для большинства игр, так как их логика обычно выполняется в детерминированном цикле, а не на основе событий. Это также обычно проще интерпретировать команды игры из входных данных, собранных одновременно, чем из многих отдельных входных данных, собранных с течением времени.

Вы опросите палку полета, вызвав FlightStick.GetCurrentReading. Эта функция возвращает FlightStickReading , содержащую состояние тестовой наклейки.

В следующем примере выполняется опрос пролетной палки для текущего состояния:

auto flightStick = myFlightSticks->GetAt(0);
FlightStickReading reading = flightStick->GetCurrentReading();

В дополнение к состоянию стике полета каждое чтение включает метку времени, которая указывает точно, когда состояние было извлечено. Метка времени полезна для связи с временем предыдущих чтений или временем имитации игры.

Чтение входных данных джойстика и регулирования

Джойстик обеспечивает аналоговое чтение между -1.0 и 1.0 в осях X, Y и Z (roll, pitch, and yaw соответственно). Для свертки значение -1.0 соответствует левой позиции джойстика, а значение 1,0 соответствует правой позиции. Для шага значение -1,0 соответствует нижней позиции джойстика, а значение 1,0 соответствует верхней позиции. Для рывка значение -1,0 соответствует самой витой позиции, в то время как значение 1,0 соответствует самой по часовой стрелке.

Во всех осях значение составляет примерно 0,0, когда джойстик находится в центре, но это нормально для точного значения, даже между последующими считываниями. Стратегии устранения этого варианта рассматриваются далее в этом разделе.

Значение свертывания джойстика считывается из свойства FlightStickReading.Roll, значение поля считывается из свойства FlightStickReading.Pitch, а значение рывка считывается из свойства FlightStickReading.Yaw:

// Each variable will contain a value between -1.0 and 1.0.
float roll = reading.Roll;
float pitch = reading.Pitch;
float yaw = reading.Yaw;

При чтении значений джойстика вы заметите, что они не надежно создают нейтральное чтение 0,0, когда джойстик находится в состоянии покоя в центре; Вместо этого они будут создавать разные значения около 0,0 каждый раз, когда джойстик перемещается и возвращается в положение центра. Чтобы устранить эти варианты, можно реализовать небольшую мертвую зону, которая представляет собой диапазон значений вблизи идеального центрального положения, которые игнорируются.

Один из способов реализовать мертвую зону заключается в том, чтобы определить, насколько далеко джойстик перемещен из центра, и игнорировать чтения, которые ближе, чем какое-то расстояние, которое вы выбираете. Вы можете вычислить расстояние примерно — это не точно, потому что чтения джойстика по сути полярны, а не планарные, значения — просто с помощью теоремы Pythagorean. Это создает радиальную мертвую зону.

В следующем примере показана базовая радиальная мертвая зона с помощью теоремы Pythagorean:

// Choose a deadzone. Readings inside this radius are ignored.
const float deadzoneRadius = 0.1f;
const float deadzoneSquared = deadzoneRadius * deadzoneRadius;

// Pythagorean theorem: For a right triangle, hypotenuse^2 = (opposite side)^2 + (adjacent side)^2
float oppositeSquared = pitch * pitch;
float adjacentSquared = roll * roll;

// Accept and process input if true; otherwise, reject and ignore it.
if ((oppositeSquared + adjacentSquared) < deadzoneSquared)
{
    // Input accepted, process it.
}

Чтение кнопок и переключателя шляпы

Каждая из двух кнопок огня на борту полета обеспечивает цифровое чтение, указывающее, нажато ли оно (вниз) или выпущено (вверх). Для повышения эффективности чтение кнопок не представлено как отдельные логические значения, а все они упакованы в одно битовое поле, представленное перечислением FlightStickButtons . Кроме того, 8-путь переключатель шляпы предоставляет направление, упакованное в одно битовое поле, представленное перечислением GameControllerSwitchPosition .

Примечание

Наклейки для полетов оснащены дополнительными кнопками, используемыми для навигации пользовательского интерфейса, таких как кнопки "Вид " и "Меню ". Эти кнопки не являются частью FlightStickButtons перечисления и могут быть прочитаны только путем доступа к наклейке полета в качестве устройства навигации пользовательского интерфейса. Дополнительные сведения см. в разделе "Контроллер навигации пользовательского интерфейса".

Значения кнопки считываются из свойства FlightStickReading.Button . Так как это свойство представляет собой битовое поле, побитовое маскирование используется для изоляции значения нужной кнопки. Кнопка нажимается (вниз) при установке соответствующего бита; в противном случае она выпущена (вверх).

В следующем примере определяется, нажимается ли кнопка FirePrimary :

if (FlightStickButtons::FirePrimary == (reading.Buttons & FlightStickButtons::FirePrimary))
{
    // FirePrimary is pressed.
}

В следующем примере определяется, выпущена ли кнопка FirePrimary :

if (FlightStickButtons::None == (reading.Buttons & FlightStickButtons::FirePrimary))
{
    // FirePrimary is released (not pressed).
}

Иногда может потребоваться определить, когда кнопка переходит от нажатия на нажатие или освобождено на нажатие, если несколько кнопок нажимаются или освобождаются, или если набор кнопок упорядочивается определенным образом, некоторые нажимаются, а не. Сведения об обнаружении каждого из этих условий см. в разделе "Обнаружение переходов кнопок" и "Обнаружение сложных договоренностей кнопок".

Значение параметра шляпы считывается из свойства FlightStickReading.HatSwitch . Так как это свойство также является битфилдом, побитовое маскирование снова используется для изоляции положения переключателя шляпы.

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

if (GameControllerSwitchPosition::Up == (reading.HatSwitch & GameControllerSwitchPosition::Up))
{
    // The hat switch is in the up position.
}

В следующем примере определяется, находится ли переключатель шляпы в центре.

if (GameControllerSwitchPosition::Center == (reading.HatSwitch & GameControllerSwitchPosition::Center))
{
    // The hat switch is in the center position.
}

См. также