主な違い
XInput と GameInput の主な違いについては、以下のセクションで説明します。C と C++
XInput API はフラットな C 関数の集合です。一方、GameInput は C++ で、(グラフィックスやオーディオ API と同様に) インターフェイスを使用します。実際には、これにより GameInput API を使用するコードが複雑になることはなく、パフォーマンスにも影響を与えません。また、GameInput の動作に慣れてくると明らかになるいくつかの利点があります。 これらのインターフェイスは COM のように見えるかもしれませんが、そうではないことを理解することが重要です。これらのインターフェイスを使用するには、参照カウントの基本的な理解のみが必要です。詳細については、GameInput の基礎 トピックの「インターフェイス」セクションを参照してください。入力の取得
XInput では、ほとんどのゲームは、接続されたデバイスを持つものが見つかるまでユーザーインデックスをループし、そのデバイスから状態を読み取ります。ゲームは次回ループしなくてもいいように、ユーザーインデックスを覚えておくことがよくあります。たとえば、次のコードは、ユーザーにコントローラーで「A を押してください」と促すゲームで典型的なものです。ランブルフィードバック
XInput では、ゲームは単にXInputSetState を呼び出してデバイスにランブル (振動) コマンドを送信します。GameInput では、ゲームはデバイスの IGameInputDevice インスタンスを取得し、その SetRumbleState メソッドを呼び出す必要があります。これら 2 つのメソッドの使用法は似ています。これは、デバイスインターフェイスが単なるデバイス識別子であるのではなく、その関数を呼び出す場合の例です。
アプリケーションのフォーカス
コンソールでは、GameInput はアプリケーションがフォーカスされているときにのみ入力を提供します。それ以外の場合、返される状態は、ユーザーがデバイスにまったく触れていないかのように、ニュートラルまたは「rest」の値を含みます。これにより、フォーカスの変化に対処する余分な入力コード (たとえば、XInputEnable を呼び出すなど) が不要になります。
PC では、入力は既定ではすべてのプロセスに送られます。将来的には、この動作は SetFocusPolicy メソッドを使用して変更可能になります。
XInputOnGameInput ラッパー
Microsoft Game Development Kit (GDK) にはXInputOnGameInput.h というヘッダーファイルが同梱されており、GameInput 上での XInput API の実装が含まれています。特にキーボードとマウスまたはその他の入力デバイスが必要な場合は、GameInput に直接移植することをお勧めします。ただし、XInputOnGameInput ラッパーは、既存の XInput コードに変更を必要とせずに、初期の移植作業をブートストラップするのに役立つ可能性があります。
XInputOnGameInput ラッパーを使用するには、次のコードを:
XInput と XInputOnGameInput の違い
一般に、XInputOnGameInput ラッパーはレガシー XInput API の直接的なドロップイン置換です。ただし、いくつかの小さな違いがあります。- 簡潔さのために、ラッパーにはゲームパッドデバイスのサポートのみがコード化されています。レーシングホイールやアーケードスティックなど、他のデバイスをサポートする必要がある場合は、GameInput を直接使用するか、XInputOnGameInput コードにこれらのデバイスのサポートを追加してください。
-
ラッパーは、ゲームがフォーカスされているときにのみゲームパッド入力を返します。ゲームがフォーカスされていない場合、返されるすべてのゲームパッドの状態は、ユーザーがゲームパッドに触れていないかのように、ニュートラルまたは「rest」値に設定されます。これは、
XInputEnableへの呼び出しの有無に関係なく行われます。 -
XUSER_MAX_COUNTの値は 4 から 8 に増加されました。これは通常、ほとんどのレガシー XInput コードに対して透過的である必要があります。ただし、コード内でのXInputGetKeystroke関数の使用を慎重にレビューし、XINPUT_KEYSTROKE構造体のUserIndexメンバーで返される最大値が 4 であることを前提としてハードコードされているものがないことを確認してください。そうしないと、バッファオーバーランが発生する可能性があります。 - いくつかの新しい関数が追加されました (下記参照)。これらは、本番コードで XInput ラッパーを引き続き使用する予定の場合にのみ関心があるはずです。
本番コードでの XInputOnGameInput の使用
XInputOnGameInput ラッパーは、GameInput API のすべてのパフォーマンス最適化を継承しており、高性能でロックフリーになるように記述されているため、本番コードでの使用に適しています。また、GameInput の広範なデバイスサポート (人気の HID ゲームパッドなど) も継承しており、API に次の新しい関数を追加します。-
XInputSetStateExはXInputSetStateに似ていますが、トリガーモーターのサポートを追加します。 -
XInputGetStateWithTokenはXInputGetStateに似ていますが、呼び出し元が特定の入力読み取りをグラフィックスフレームに関連付けて、後で PIX で分析するために D3DX フレームパイプライントークンを提供できます。[!NOTE] May Preview リリースでは、基盤となる GameInput コードが完全には実装されていないため、
XInputGetStateWithTokenは現在XInputGetStateと同じように動作します。 -
XInputGetDeviceIdは、指定されたユーザーインデックスのデバイスに対してAPP_LOCAL_DEVICE_IDを返します。この ID を IGameInput の FindDeviceFromId メソッドに渡すと、そのユーザーインデックスに対応する IGameInputDevice が返されます。これを使用すると、XInput ラッパー経由では公開されていない GameInput API の追加機能にアクセスできます。
ラッパーコードの最適化
既定では、XInputOnGameInput ラッパーはレガシー XInput API とドロップイン互換になるように構成されています。100% 互換の動作を必要としないゲームは、次のプリプロセッサマクロのいずれかを定義することで、ラッパーの動作とパフォーマンスを微調整できます。XINPUT_ON_GAMEINPUT_EXPLICIT_INITIALIZATION
既定では、XInput ラッパーは、ラッパー関数のいずれかが最初に呼び出されるときに、基盤となる GameInput API を自動的に遅延初期化します。これにより既存の XInput コードとのドロップイン互換性が保証されますが、いくつかの小さな欠点があります。- 最初の XInput ラッパー関数呼び出しの実行時間は、通常よりも長くなります。
- すべての XInput ラッパー関数は、呼び出されるたびに遅延初期化が実行されたかどうかをチェックする必要があります。これはグローバル変数の単純なテストなので、分岐予測子がコストを軽減するはずですが、余分なオーバーヘッドです。
- 失敗することは決してないはずですが、基盤となる GameInput API の遅延初期化が成功したかどうかを判断する方法はありません。
- 基盤となる IGameInput インスタンスは、XInput ラッパーのグローバル変数がクリーンアップされる (モジュールのアンロードまたはプロセスの終了のいずれかによる) まで解放されません。
XINPUT_ON_GAMEINPUT_EXPLICIT_INITIALIZATION マクロを定義することで、ラッパーの初期化とシャットダウンを手動で制御できます。これにより、初期化とシャットダウンがいつ発生するかを正確に制御するために呼び出すことができる、XInputOnGameInputInitialize と XInputOnGameInputUninitialize の 2 つの新しい関数が追加されます。
XINPUT_ON_GAMEINPUT_NO_XINPUTENABLE
XInputEnable 関数を実装するために必要なコードは、XInputGetState、XInputGetStateWithToken、XInputSetState、XInputSetStateEx、および XInputGetKeystroke 関数のすべての呼び出しに追加のオーバーヘッドを加えます。コードが XInputEnable を呼び出さない場合、またはコードから容易に排除できる場合は、XINPUT_ON_GAMEINPUT_NO_XINPUTENABLE マクロを定義することで、XInputEnable のサポートとそれに伴う関連オーバーヘッドが削除されます。基盤となる GameInput コードはとにかくフォーカスの変更で XInputEnable の機能を自動的に実行するため、ほとんどのゲームは可能であればこのマクロを定義したいと思うでしょう。
XINPUT_ON_GAMEINPUT_NO_XINPUTGETKEYSTROKE
XInputGetKeystroke 関数を実装するために必要なコードは、ラッパーの実装にいくつかの追加の関数と変数を追加します。他の XInput API 関数にオーバーヘッドを追加しませんが、コードが XInputGetKeystroke を呼び出さない場合は、XINPUT_ON_GAMEINPUT_NO_XINPUTGETKEYSTROKE マクロを定義することで、XInput ラッパーのコード/データサイズをわずかに減らすことができます。
