Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
На этой странице описаны основы программирования для гоночных колес в Xbox One с помощью Windows.Gaming.Input.RacingWheel и связанных API для универсальной платформы Windows (UWP).
Прочитав эту страницу, вы узнаете:
- как собрать список подключенных гоночных колес и их пользователей
- как определить, что гоночное колесо было добавлено или удалено
- как считывать данные с одного или нескольких гоночных колес
- отправка команд принудительной обратной связи
- Поведение гоночных колес в качестве устройств навигации пользовательского интерфейса
Обзор гоночного колеса
Гоночные рули — это устройства ввода, которые напоминают ощущения от кабины гоночного автомобиля. Гоночные колеса являются идеальным устройством ввода для аркадного стиля и симуляции гоночных игр, которые имеют автомобили или грузовики. Гоночные колеса поддерживаются в UWP-приложениях для Windows 10 и Windows 11 и Xbox One в пространстве имен Windows.Gaming.Input.
Гоночные колеса предлагаются в различных ценовых категориях, как правило, имея больше и лучше возможностей ввода и обратной связи с усилием по мере роста цен. Все гоночные колеса оснащены аналоговым рулем, аналоговым регулированием и тормозными элементами управления, а также некоторыми кнопками на колесе. Некоторые гоночные колеса также оснащены аналоговым сцеплением и ручным тормозом, переключателями передач и возможностями обратной связи. Не все гоночные колеса оснащены одинаковыми наборами функций, а также могут отличаться в их поддержке некоторых функций, например, рулевы могут поддерживать различные диапазоны поворота и смены шаблонов могут поддерживать разные числа шестеренок.
Возможности устройств
Различные гоночные колеса предлагают различные наборы дополнительных возможностей устройства и различные уровни поддержки этих возможностей; этот уровень вариации между одним типом входного устройства является уникальным среди устройств, поддерживаемых API Windows.Gaming.Input . Кроме того, большинство устройств, с которыми вы столкнетесь, будет поддерживать по крайней мере некоторые необязательные возможности или другие варианты. Из-за этого важно определить возможности каждого подключенного гоночного колеса по отдельности и поддерживать полный вариант возможностей, которые имеет смысл для вашей игры.
Дополнительные сведения см. в разделе "Определение возможностей гоночного колеса".
Обратная связь с усилием
Некоторые гоночные колеса предлагают настоящую обратную связь по усилию, то есть они могут применять фактические силы на ось управления, например, рулевое колесо, а не просто вибрацию. Игры используют эту способность создавать большее чувство погружения (имитация повреждения аварии, "дорожное чувство") и увеличить вызов вождения хорошо.
Дополнительные сведения см. в обзоре обратной связи силы.
Навигация пользовательского интерфейса
Чтобы облегчить бремя поддержки различных устройств ввода для навигации в пользовательском интерфейсе и поощрять согласованность между играми и устройствами, большинство физических устройств ввода одновременно выполняют роль отдельного логического устройства ввода, называемого контроллером пользовательского интерфейса для навигации . Контроллер навигации пользовательского интерфейса предоставляет общий словарь для команд навигации пользовательского интерфейса на устройствах ввода.
Из-за их уникального фокуса на аналоговые элементы управления и степень вариации между различными гоночными колесами, они обычно оснащены цифровым D-pad, View, Menu, A, B, Xи Y кнопками, которые напоминают кнопки геймпада ; эти кнопки не предназначены для поддержки команд игрового процесса и не могут быть легко доступны, как кнопки гоночного колеса.
В качестве контроллера навигации пользовательского интерфейса гоночные колеса сопоставляют необходимый набор команд навигации с левым джойстиком, D-pad, кнопками View, Menu, Aи B.
| Команда навигации | Входные данные гоночного колеса |
|---|---|
| Вверх | крестовина вверх |
| Вниз | кнопка D-pad вниз |
| Лево | D-pad слева |
| Правильно | крестовина вправо |
| Просмотреть | Кнопка "Просмотреть" |
| Меню | Кнопка меню |
| Принять | Кнопка |
| Отменить | Кнопка B |
Кроме того, некоторые гоночные колеса могут сопоставлять часть необязательного набора команд навигации с другими входными сигналами, которые они поддерживают, но сопоставления команд могут отличаться от устройства к устройству. Рассмотрите возможность поддержки этих команд, но убедитесь, что эти команды не являются важными для навигации по интерфейсу игры.
| Команда навигации | Входные данные гоночного колеса |
|---|---|
| Пэйдж Ап | Различается |
| Страница вниз | Различается |
| Левая страница | Различается |
| Страница справа | Различается |
| Прокрутка вверх | Различается |
| Прокрутите вниз | Различается |
| Прокрутка влево | Различается |
| Прокрутка вправо | Различается |
| Контекст 1 | Кнопка X (обычно) |
| Контекст 2 | Кнопка Y (обычно) |
| Контекст 3 | Различается |
| Контекст 4 | Различается |
Обнаружение и отслеживание гоночных колес
Обнаружение и отслеживание гоночных колес работает точно так же, как и для геймпадов, за исключением класса RacingWheel вместо класса Gamepad . См. раздел «Геймпад и вибрация» для получения дополнительной информации.
Считывание данных с гоночного колеса
После идентификации гоночных колес, которые вас интересуют, вы готовы собрать входные данные от них. Тем не менее, в отличие от некоторых других видов входных данных, которые вы можете использовать, гоночные рули не сигнализируют об изменениях состояния посредством создания событий. Вместо этого вы регулярно отслеживаете их текущие состояния, опросом их.
Опрос состояния гоночного колеса
Опрос захватывает моментальный снимок гоночного колеса в точный момент времени. Такой подход к сбору входных данных подходит для большинства игр, так как их логика обычно выполняется в детерминированном цикле, а не на основе событий; Это также, как правило, проще интерпретировать команды игры из входных данных, собранных одновременно, чем из многих отдельных входных данных, собранных с течением времени.
Вы опрашиваете гоночное колесо, вызвав GetCurrentReading; эта функция возвращает RacingWheelReading, который содержит состояние гоночного колеса.
В следующем примере проводится опрос состояния гоночного колеса.
auto racingwheel = myRacingWheels[0];
RacingWheelReading reading = racingwheel->GetCurrentReading();
В дополнение к состоянию гоночного колеса каждое чтение включает метку времени, которая указывает точно, когда состояние было извлечено. Метка времени полезна для связи с временем предыдущих чтений или временем имитации игры.
Определение возможностей гоночного колеса
Многие из элементов управления гоночных рулей являются опциональными или поддерживают различные варианты даже среди необходимых, поэтому вам необходимо определить возможности каждого гоночного руля по отдельности, прежде чем вы сможете обработать показания, собранные в каждом отслеживании данных гоночного руля.
Необязательные элементы управления — это ручной тормоз, сцепление и кулисный переключатель; Вы можете определить, поддерживает ли подключенное гоночное колесо, считав свойства HasHandbrake, HasClutchи HasPatternShifter соответственно. Элемент управления поддерживается, если значение свойства true; в противном случае его поддержка отсутствует.
if (racingwheel->HasHandbrake)
{
// the handbrake is supported
}
if (racingwheel->HasClutch)
{
// the clutch is supported
}
if (racingwheel->HasPatternShifter)
{
// the pattern shifter is supported
}
Кроме того, элементы управления, которые могут отличаться, это рулевое колесо и рычаг коробки передач. Рулевое колесо может отличаться по степени физического поворота, которое может поддерживать само рулевое управление, в то время как переключатель передач может различаться в зависимости от количества отдельных передних передач, которые он поддерживает. Вы можете определить наибольший угол поворота данного колеса, прочитав свойство MaxWheelAngle гоночного колеса; его значение — это максимальный поддерживаемый физический угол в градусах по часовой стрелке (положительный), который также поддерживается в направлении против часовой стрелки (отрицательные градусы). Вы можете определить максимальную передачу переднего хода, которую поддерживает рычаг переключения передач, считав свойство MaxPatternShifterGear рулевого колеса для гонок; его значение обозначает наиболее высокую поддерживаемую передачу, включая все предыдущие—это значит, если его значение равно 4, тогда рычаг переключения передач поддерживает заднюю, нейтральную, первую, вторую, третью и четвертую передачи.
auto maxWheelDegrees = racingwheel->MaxWheelAngle;
auto maxShifterGears = racingwheel->MaxPatternShifterGear;
Наконец, некоторые гоночные колеса поддерживают обратную связь через рулевое колесо. Вы можете определить, поддерживается ли подключенным гоночным колесом обратная связь по усилию, прочитав свойство WheelMotor. Обратная связь с усилием поддерживается, если WheelMotor не null; в противном случае она не поддерживается.
if (racingwheel->WheelMotor != nullptr)
{
// force feedback is supported
}
Сведения о том, как использовать функцию обратной связи на гоночных рулях, которые её поддерживают, см. в разделе Обзор функции обратной связи.
Чтение кнопок
Каждая из кнопок гоночного колеса — четыре направления D-pad, кнопки Предыдущая передача и Следующая передача, а также 16 дополнительных кнопок — предоставляет цифровое показание, указывающее, нажата ли она (вниз) или отпущена (вверх). Для повышения эффективности чтение кнопок не представлено в виде отдельных логических значений; вместо этого они все упакованы в одно битовое поле, представленное перечислением RacingWheelButtons .
Замечание
Гоночные колеса оснащены дополнительными кнопками, используемыми для навигации по пользовательскому интерфейсу, такими как кнопки Просмотр и Меню. Эти кнопки не являются частью перечисления RacingWheelButtons и могут быть прочитаны только при использовании гоночного колеса в роли устройства навигации в пользовательском интерфейсе. Дополнительные сведения см. в разделе "Устройство навигации пользовательского интерфейса".
Значения кнопок считываются из свойства Buttons структуры RacingWheelReading. Так как это свойство представляет собой битовое поле, побитовое маскирование используется для изоляции значения нужной кнопки. Кнопка нажата (вниз), если установлен соответствующий бит; в противном случае она отпущена (вверх).
В следующем примере определяется, нажата ли кнопка Next Gear.
if (RacingWheelButtons::NextGear == (reading.Buttons & RacingWheelButtons::NextGear))
{
// Next Gear is pressed
}
В следующем примере определяется, выпущена ли кнопка Next Gear.
if (RacingWheelButtons::None == (reading.Buttons & RacingWheelButtons::NextGear))
{
// Next Gear is released (not pressed)
}
Иногда может потребоваться определить, когда кнопка переходит от нажатия к освобождению или от освобождения к нажатию, нажаты или освобождены несколько кнопок, или если набор кнопок расположен определенным образом — некоторые нажаты, а некоторые нет. Сведения о том, как обнаруживать эти условия, см. в разделе Обнаружение переходов состояний кнопок и Обнаружение сложных конфигураций кнопок.
Чтение обода
Рулевое колесо — это обязательный элемент управления, обеспечивающий аналоговые показания в диапазоне от -1,0 до +1,0. Значение -1.0 соответствует левому краю колесика; Значение +1.0 соответствует правой позиции. Значение рулевого колеса считывается из свойства Wheel структуры RacingWheelReading.
float wheel = reading.Wheel; // returns a value between -1.0 and +1.0.
Хотя показания колес соответствуют различным степени физического поворота в фактическом колесе в зависимости от диапазона поворота, поддерживаемого физическим гоночным колесом, обычно не требуется масштабировать показания колес; колеса, поддерживающие большую степень поворота, просто обеспечивают большую точность.
Считывание данных с дросселя и тормоза
Для дросселя и тормоза требуются органы управления, которые предоставляют аналоговые показания между 0,0 (полностью освобождены) и 1,0 (полностью нажаты), представленные как значения с плавающей запятой. Значение элемента управления регулированием считывается из Throttle свойства структуры RacingWheelReading ; значение элемента управления тормозом считывается из Brake свойства.
float throttle = reading.Throttle; // returns a value between 0.0 and 1.0
float brake = reading.Brake; // returns a value between 0.0 and 1.0
Настройка ручного тормоза и сцепления
Ручной тормоз и сцепление являются необязательными элементами управления, которые обеспечивают аналоговое чтение от 0,0 (полностью выпущено) до 1,0 (полностью нажато), представленные как числа с плавающей точкой. Значение элемента управления ручным тормозом считывается из свойства Handbrake структуры RacingWheelReading; значение элемента управления сцеплением считывается из свойства Clutch.
float handbrake = 0.0;
float clutch = 0.0;
if(racingwheel->HasHandbrake)
{
handbrake = reading.Handbrake; // returns a value between 0.0 and 1.0
}
if(racingwheel->HasClutch)
{
clutch = reading.Clutch; // returns a value between 0.0 and 1.0
}
Чтение устройства изменения шаблона
Смена шаблона — это необязательный элемент управления, предоставляющий цифровое чтение между -1 и MaxPatternShifterGear, представленный как целочисленное значение со знаком. Значение -1 или 0 соответствует обратной и нейтральной передаче, соответственно; все более положительные значения соответствуют более высоким передачам вперед до MaxPatternShifterGear, включительно. Значение переключателя шаблонов считывается из свойства PatternShifterGear структуры RacingWheelReading.
if (racingwheel->HasPatternShifter)
{
gear = reading.PatternShifterGear;
}
Замечание
Переключатель режимов, при условии поддержки, используется вместе с кнопками Previous Gear и Next Gear, которые также влияют на текущую передачу автомобиля игрока. Простая стратегия объединения этих входных данных, когда оба присутствуют, заключается в том, чтобы игнорировать рычаг переключения передач (и сцепление), если игрок выбирает автоматическую коробку передач для своего автомобиля, и игнорировать кнопки Предыдущая и Следующая передача, когда игрок выбирает ручную коробку передач для своего автомобиля, только если их гоночное колесо оснащено элементом управления рычагом переключения передач. Вы можете реализовать другую стратегию объединения, если это не подходит для вашей игры.
Запуск примера InputInterfacing
Пример приложения InputInterfacingUWP на GitHub демонстрирует, как использовать гоночные рули и различные типы устройств ввода в тандеме, а также как эти устройства ввода выполняют функцию контроллеров навигации пользовательского интерфейса.
Общие сведения о принудительной обратной связи
Многие гоночные рули оснащены системой обратной связи, чтобы обеспечить более захватывающий и сложный опыт вождения. Гоночные колеса, поддерживающие обратную связь силы, обычно оснащены одним двигателем, который применяет силу к рулевому колесу вдоль одной оси, оси поворота колеса. Поддержка обратной связи реализована в UWP приложениях для Windows 10 или Windows 11 и Xbox One через пространство имен Windows.Gaming.Input.ForceFeedback.
Замечание
API с обратной связью могут поддерживать несколько осей силы, но гоночное колесо в настоящее время не поддерживает никакую ось обратной связи, кроме оси поворота колеса.
Использование тактильной обратной связи
В этих разделах описаны основы программирования эффектов обратной связи для гоночных колес. Обратная связь применяется с помощью эффектов, которые сначала загружаются на устройство принудительной обратной связи, а затем могут быть запущены, приостановлены, возобновлены и остановлены таким образом, как звуковые эффекты; однако сначала необходимо определить возможности обратной связи гоночного колеса.
Определение возможностей принудительной обратной связи
Вы можете определить, поддерживается ли подключенным гоночным колесом обратная связь по усилию, прочитав свойство WheelMotor. Принудительный отзыв не поддерживается, если WheelMotornull; в противном случае обратная связь поддерживается, и вы можете продолжить определение конкретных возможностей обратной связи двигателя, таких как оси, которые могут повлиять на него.
if (racingwheel->WheelMotor != nullptr)
{
auto axes = racingwheel->WheelMotor->SupportedAxes;
if(ForceFeedbackEffectAxes::X == (axes & ForceFeedbackEffectAxes::X))
{
// Force can be applied through the X axis
}
if(ForceFeedbackEffectAxes::Y == (axes & ForceFeedbackEffectAxes::Y))
{
// Force can be applied through the Y axis
}
if(ForceFeedbackEffectAxes::Z == (axes & ForceFeedbackEffectAxes::Z))
{
// Force can be applied through the Z axis
}
}
Загрузка эффектов обратной связи
Эффекты обратной связи загружаются на устройство обратной связи, где они воспроизводятся автономно по команде вашей игры. Предоставляется ряд основных эффектов, и пользовательские эффекты можно создавать с помощью класса, реализующего интерфейс IForceFeedbackEffect.
| Класс эффектов | Описание эффекта |
|---|---|
| ConditionForceEffect | Эффект, который применяет переменную силу в ответ на текущие данные датчика в устройстве. |
| Эффект постоянной силы | Эффект, который применяет константную силу вдоль вектора. |
| Эффект периодической силы | Эффект, который применяет переменную силу, определенную волнообразной формой, вдоль вектора. |
| RampForceEffect | Эффект, который применяет линейно увеличивающуюся или уменьшающуюся силу вдоль вектора. |
using FFLoadEffectResult = ForceFeedback::ForceFeedbackLoadEffectResult;
auto effect = ref new Windows.Gaming::Input::ForceFeedback::ConstantForceEffect();
auto time = TimeSpan(10000);
effect->SetParameters(Windows::Foundation::Numerics::float3(1.0f, 0.0f, 0.0f), time);
// Here, we assume 'racingwheel' is valid and supports force feedback
IAsyncOperation<FFLoadEffectResult>^ request
= racingwheel->WheelMotor->LoadEffectAsync(effect);
auto loadEffectTask = Concurrency::create_task(request);
loadEffectTask.then([this](FFLoadEffectResult result)
{
if (FFLoadEffectResult::Succeeded == result)
{
// effect successfully loaded
}
else
{
// effect failed to load
}
}).wait();
Использование эффектов силовой обратной связи
После загрузки все эффекты могут быть запущены, приостановлены, возобновлены и остановлены синхронно путем вызова функций в свойстве WheelMotor гоночного колеса или по отдельности путем вызова функций для самого эффекта обратной связи. Как правило, необходимо загрузить все эффекты, которые вы хотите использовать на устройстве обратной связи перед началом игрового процесса, а затем использовать соответствующие SetParameters функции для обновления эффектов в процессе выполнения игрового процесса.
if (ForceFeedbackEffectState::Running == effect->State)
{
effect->Stop();
}
else
{
effect->Start();
}
Наконец, вы можете асинхронно включить, отключить или сбросить всю систему обратной связи силы на определенном гоночном колесе всякий раз, когда вам нужно.