Гоночный колесо и обратная связь силы

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

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

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

Обзор гоночного колеса

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

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

Возможности устройства

Различные гоночные колеса предлагают различные наборы дополнительных возможностей устройства и различные уровни поддержки этих возможностей; этот уровень вариации между одним типом входного устройства является уникальным среди устройств, поддерживаемых API Windows.Gaming.Input . Кроме того, большинство устройств, с которыми вы столкнетесь, будет поддерживать по крайней мере некоторые необязательные возможности или другие варианты. Из-за этого важно определить возможности каждого подключенного гоночного колеса по отдельности и поддерживать полный вариант возможностей, которые имеет смысл для вашей игры.

Дополнительные сведения см. в разделе "Определение возможностей гоночного колеса".

Принудительное отзыв

Некоторые гоночные колеса предлагают истинный отзыв силы , то есть они могут применять фактические силы на оси управления, такие как их рулевое колесо , а не просто вибрация. Игры используют эту способность создать большее чувство погружения (имитация повреждения аварии, "дорожное чувство") и увеличить задачу вождения хорошо.

Дополнительные сведения см. в обзоре обратной связи force.

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

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

Из-за их уникального фокуса на аналоговых элементах управления и степени вариации между различными гоночными колесами, они обычно оснащены цифровым D-pad, View, Menu, A, B, X и Y кнопок, которые похожи на геймпад. Эти кнопки не предназначены для поддержки команд игрового процесса и не могут быть легко доступны как гоночные кнопки колеса.

В качестве контроллера навигации пользовательского интерфейса гоночные колеса сопоставляют необходимый набор команд навигации с левым пальцем, D-pad, View, Menu, A и B button.

Команда навигации Входные данные гоночного колеса
Up D-pad up
Down D-pad down
Left D-pad слева
Right D-pad right
Представление Кнопка "Просмотреть"
Меню Кнопка меню
Принять Кнопка
Cancel Кнопка B

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

Команда навигации Входные данные гоночного колеса
Page Up Различается
Page Down Различается
Страница слева Различается
Страница справа Различается
Прокрутка вверх Различается
Прокрутите вниз Различается
Прокрутка влево Различается
Прокрутка вправо Различается
Контекст 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
}

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

Чтение кнопок

Каждая из кнопок гоночного колеса — четыре направления 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;
}

Примечание.

Переключатель шаблона, где поддерживается, существует вместе с необходимыми кнопками предыдущей передачи и next Gear , которые также влияют на текущую передачу автомобиля игрока. Простая стратегия объединения этих входных данных, где оба присутствуют, заключается в том, чтобы игнорировать смену шаблона (и сцепление), когда игрок выбирает автоматическую передачу для своего автомобиля, и игнорировать кнопки "Предыдущая и Следующая шестеренка ", когда игрок выбирает ручную передачу для своего автомобиля, только если их гоночный колесо оснащено элементом управления сменой шаблона. Вы можете реализовать другую стратегию объединения, если это не подходит для вашей игры.

Запуск примера InputInterfacing

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

Общие сведения о принудительной обратной связи

Многие гоночные колеса обладают возможностью обратной связи, чтобы обеспечить более иммерсивный и сложный опыт вождения. Гоночные колеса, поддерживающие обратную связь силы, обычно оснащены одним двигателем, который применяет силу к рулевому колесу вдоль одной оси, оси поворота колеса. Обратная связь принудительно поддерживается в приложениях UWP для Windows 10 или Windows 11 и Xbox One UWP через пространство имен Windows.Gaming.Input.ForceFeedback .

Примечание.

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

Использование обратной связи с принудительной силой

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

Определение возможностей принудительной обратной связи

Вы можете определить, поддерживает ли подключенный гоночный колесо принудительной обратной связи, прочитав свойство WheelMotor гоночного колеса. Обратная связь принудительно не поддерживается, если WheelMotor имеет значение NULL; в противном случае поддерживается обратная связь, и вы можете продолжить определение конкретных возможностей обратной связи двигателя, таких как оси, которые могут повлиять на него.

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 Эффект, который применяет переменную силы в ответ на текущий датчик на устройстве.
ConstantForceEffect Эффект, который применяет константную силу вдоль вектора.
PeriodicForceEffect Эффект, который применяет переменную силу, определенную волнообразной формой, вдоль вектора.
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();
}

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

См. также