このページでは、 Windows.Gaming.Input.RacingWheel を使用した Xbox One でのレーシング ハンドルのプログラミングの基本と、ユニバーサル Windows プラットフォーム (UWP) 用の関連 API について説明します。
このページを読むと、次の内容が学習されます。
- 接続されているレーシング ハンドルとそのユーザーの一覧を収集する方法
- レーシング ホイールが追加または削除されたことを検出する方法
- 1 つ以上のレーシング ホイールから入力を読み取る方法
- フォース フィードバック コマンドを送信する方法
- レーシング ホイールが UI ナビゲーション デバイスとして動作する方法
レーシング ホイールの概要
レーシングホイールは、本物のレーシングカーコックピットの感覚に似た入力デバイスです。 レーシングホイールは、アーケードスタイルとシミュレーションスタイルの両方のレーシングゲームに最適な入力デバイスです。 レーシング ホイールは、 Windows.Gaming.Input 名前空間によって Windows 10 または Windows 11 および Xbox One UWP アプリでサポートされています。
レーシング ホイールは、さまざまな価格ポイントで提供され、一般に、価格ポイントの上昇に合わせ、より多くのより良い入力とフォース フィードバック機能を備えています。 すべてのレーシングホイールには、アナログステアリングホイール、アナログスロットルとブレーキコントロール、およびいくつかのオンホイールボタンが装備されています。 一部のレーシングホイールには、アナログクラッチとハンドブレーキコントロール、パターンシフター、フォースフィードバック機能が追加されています。 すべてのレーシング ホイールに同じ機能セットが装備されているわけではありません。また、特定の機能に対するサポートも異なる場合があります。たとえば、ステアリング ホイールは、異なる範囲の回転をサポートし、パターン シフターは異なる数のギアをサポートする場合があります。
デバイスの機能
異なるレーシングホイールは、オプションのデバイス機能の異なるセットと、それらの機能に対するさまざまなレベルのサポートを提供します。単一の種類の入力デバイス間のこのレベルのバリエーションは、 Windows.Gaming.Input API でサポートされているデバイス間で一意です。 さらに、遭遇するほとんどのデバイスでは、少なくともいくつかのオプション機能や他のバリエーションがサポートされます。 このため、接続されている各レーシング ホイールの機能を個別に決定し、ゲームにとって意味のある機能の完全なバリエーションをサポートすることが重要です。
詳細については、「 レーシング ホイールの機能の決定」を参照してください。
フィードバックを強制する
レーシング ホイールの中には、単純な振動だけでなく、ステアリング ホイールなどの制御軸に実際の力を適用できる、真のフォース フィードバックを提供するものもあります。 ゲームでは、この機能を使用して、より大きな没入感 (シミュレートされたクラッシュダメージ、"道路感") を作成し、うまく運転する課題を増やします。
詳細については、「 フォース フィードバックの概要」を参照してください。
UI ナビゲーション
ユーザー インターフェイス ナビゲーションのさまざまな入力デバイスをサポートする負担を軽減し、ゲームとデバイス間の一貫性を促進するために、ほとんどの物理入力デバイスは、UI ナビゲーション コントローラーと呼ばれる個別の論理入力デバイスとして同時に機能します。 UI ナビゲーション コントローラーは、入力デバイス間の UI ナビゲーション コマンドに共通のボキャブラリを提供します。
アナログコントロールに独自の焦点を当て、異なるレーシングホイール間のバリエーションの程度のために、彼らは通常、ゲームパッドのものと似たデジタルDパッド、ビュー、メニュー、A、B、X、およびYボタンが装備されています。これらのボタンはゲームプレイ コマンドをサポートするためのものではなく、レーシング ホイール ボタンとして簡単にアクセスすることはできません。
UI ナビゲーション コントローラーとして、レーシング ホイールは、ナビゲーション コマンドの
ナビゲーション コマンド | レーシング ホイール入力 |
---|---|
上方向 | D パッドアップ |
下方向 | ディーパッド下 |
左 | D-パッド左 |
はい | D パッド右 |
表示 | [表示] ボタン |
メニュー | メニュー ボタン |
同意する | ボタン |
キャンセル | B ボタン |
さらに、一部のレーシング ホイールでは 、オプション のナビゲーション コマンドのセットの一部がサポートされている他の入力にマップされる場合がありますが、コマンド マッピングはデバイスによって異なる場合があります。 これらのコマンドもサポートすることを検討してください。ただし、これらのコマンドがゲームのインターフェイス内を移動するために不可欠ではないことを確認してください。
ナビゲーション コマンド | レーシング ホイール入力 |
---|---|
ページアップ | 状況に応じて異なる |
ページダウン | 状況に応じて異なる |
左ページ | 状況に応じて異なる |
ページの右側 | 状況に応じて異なる |
上へスクロール | 状況に応じて異なる |
下へスクロール | 状況に応じて異なる |
左へスクロール | 状況に応じて異なる |
右にスクロール | 状況に応じて異なる |
コンテキスト 1 | X ボタン (一般的) |
コンテキスト 2 | Y ボタン (一般的) |
コンテキスト 3 | 状況に応じて異なる |
コンテキスト 4 | 状況に応じて異なる |
レーシング ホイールを検出して追跡する
レーシング ホイールの検出と追跡は、ゲームパッド クラスではなく RacingWheel クラスを除き、 ゲームパッド の場合とまったく同じように動作します。 詳細については ゲームパッドと振動 を参照してください。
レーシングホイールを読み取る
興味のあるレーシング用ホイールを特定したら、それらからのフィードバックを集める準備が整いました。 ただし、他の種類の入力とは異なり、レーシング ホイールはイベントを発生させて状態変化を伝えません。 代わりに、彼らの現在の状態を 定期的に読み取るためにポーリングします。
レーシング ホイールのポーリング
ポーリングは、正確な時点でレーシング ホイールのスナップショットをキャプチャします。 入力収集に対するこのアプローチは、ほとんどのゲームに適しています。そのロジックは通常、イベントドリブンではなく確定的なループで実行されるためです。また、一般に、一度に収集された入力からゲーム コマンドを解釈する方が、時間の経過と同時に収集される多数の単一の入力からのコマンドよりも簡単です。
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 の場合、パターン シフターはリバース、ニュートラル、1 番目、2 番目、3 番目、および 4 番目のギアをサポートします。
auto maxWheelDegrees = racingwheel->MaxWheelAngle;
auto maxShifterGears = racingwheel->MaxPatternShifterGear;
最後に、一部のレーシング ホイールはステアリング ホイールを介したフォース フィードバックをサポートします。 接続されたレーシング ホイールがフォース フィードバックをサポートしているかどうかを判断するには、レーシング ホイールの WheelMotor プロパティを読み取ります。
WheelMotor
が null でない場合は強制フィードバックがサポートされます。それ以外の場合はサポートされません。
if (racingwheel->WheelMotor != nullptr)
{
// force feedback is supported
}
サポートするレーシング ホイールのフォース フィードバック機能を使用する方法については、「 フォース フィードバックの概要」を参照してください。
ボタンの読み取り
各レーシングホイールボタン(Dパッドの4方向、前のギア ボタン、次のギア ボタン、および16個の追加ボタン)は、押された(下)か離されている(上)かを示すデジタル読み取り値を提供します。 効率を高める目的で、ボタンの読み取り値は個々のブール値として表されません。代わりに、 それらはすべて RacingWheelButtons 列挙型で表される単一のビットフィールドにパックされます。
注
レーシング ホイールには、 表示 ボタンや メニュー ボタンなどの UI ナビゲーションに使用される追加のボタンが装備されています。 これらのボタンは RacingWheelButtons
列挙体の一部ではなく、UI ナビゲーション デバイスとしてレーシング ホイールにアクセスすることによってのみ読み取ることができます。 詳細については、「 UI ナビゲーション デバイス」を参照してください。
ボタンの値は、Buttons
構造体の プロパティから読み取られます。 このプロパティはビットフィールドであるため、関心のあるボタンの値を分離するためにビットごとのマスクが使用されます。 対応するビットが設定されている場合、ボタンは押されます(下)。それ以外の場合は、リリース (アップ) されます。
次の例では、[ 次の歯車 ] ボタンが押されているかどうかを確認します。
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
構造体の プロパティから読み取られます。
float wheel = reading.Wheel; // returns a value between -1.0 and +1.0.
ホイールの読み取り値は、実際のレーシング ホイールでサポートされる回転の範囲に応じて、実際のホイールの物理的な回転の角度が異なりますが、通常はホイールの読み取り値をスケーリングする必要はありません。より大きな回転度をサポートするホイールは、より高い精度を提供するだけです。
スロットルとブレーキの読み取り
スロットルとブレーキは、それぞれが浮動小数点値として表される 0.0 (完全にリリース) から 1.0 (完全に押された) までのアナログ読み取り値を提供する必須のコントロールです。 スロットル コントロールの値はThrottle
構造体の プロパティから読み取られます。ブレーキ コントロールの値は、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
構造体内の プロパティから読み取り、クラッチコントロールの値は 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(両端を含む) までの上位ギアに対応します。 パターン シフターの値は、RacingWheelReading 構造体の PatternShifterGear プロパティから読み取られます。
if (racingwheel->HasPatternShifter)
{
gear = reading.PatternShifterGear;
}
注
サポートされているパターン シフターは、プレイヤーの車の現在のギアにも影響する、必要な [前のギア ] ボタンと [次のギア ] ボタンと共に存在します。 両方が存在するこれらの入力を統一するための簡単な戦略は、プレイヤーが自分の車の自動トランスミッションを選択したときにパターンシフター(とクラッチ)を無視し、プレイヤーがレーシングホイールにパターンシフターコントロールが装備されている場合にのみ、車の手動トランスミッションを選択したときに 前 と 次のギア のボタンを無視することです。 これがゲームに適していない場合は、別の統一戦略を実装できます。
InputInterfacing サンプルを実行する
GitHub の InputInterfacingUWP サンプル アプリは、レーシング ホイールとさまざまな種類の入力デバイスを並行して使用する方法を示しています。また、これらの入力デバイスが UI ナビゲーション コントローラーとして動作する方法についても説明します。
フォースフィードバックの概要
多くのレーシング ホイールには、よりイマーシブで困難な運転体験を提供するフォース フィードバック機能があります。 フォース フィードバックをサポートするレーシング ホイールには、通常、1 つの軸 (ホイールの回転軸) に沿ってステアリング ホイールに力を加える 1 つのモーターが装備されています。 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 インターフェイスを実装するクラスを使用して作成できます。
エフェクトクラス | 効果の説明 |
---|---|
条件強制効果 | デバイス内の現在のセンサーに応答して可変力を適用する効果。 |
一定の力効果 | ベクトルに沿って定数フォースを適用する効果。 |
周期的力効果 | ベクトルに沿って、波形によって定義された可変力を適用する効果。 |
ランプフォースエフェクト | ベクトルに沿って線形的に増加/減少する力を適用する効果。 |
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();
}
最後に、必要に応じて、特定のレーシング ホイールでフォース フィードバック システム全体を非同期的に有効、無効、またはリセットできます。