Рукоятка управления полетом
На этой странице описаны основы программирования для сертифицированных на 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.
}