GameInput の基礎
ほとんどの従来の Microsoft 入力 API はデバイス中心です。つまり、アプリケーション コードは、入力を読み取る前に、通常は何らかの列挙パターンを介して、サポートする入力デバイスを最初に見つける必要があります。 入力のニーズが比較的単純なほとんどのゲームでは、こうした処理のために、多くの余分なコードが追加され、複雑さが増します。
一方、GameInput API は、入力中心の API です。 アプリケーションは、まず目的の入力を見つけてから、必要に応じてその入力を生成したデバイスに対してクエリを実行できます。 これによってアルゴリズムがより自然になり、コードもより単純になります。
入力ストリームのアーキテクチャ
GameInput は、入力ストリームの概念に基づいて構築されています。システムに接続されているすべてのデバイスからの入力は、入力が発生した順に、入力イベントの 1 つの連続したストリームに転送されます。 複数のデバイスが同時に入力を生成すると、入力イベントの自然なインタリーブが発生します。 複数の入力デバイスからの入力ストリームの例を次に示します。
この例では、4 台のデバイスが同時に入力を送信しています。 四角で囲まれた数字は入力が送信された順序を示し、色はその入力を送信したデバイスを示します。 したがって、この例では最初のゲームパッドが最初の入力を送信し、キーボードが 2 番目の入力を送信し、マウスが 3 番目の入力を送信し、2 番目のゲームパッドが 4 番目の入力を送信していることになります。
入力ストリームに含まれる各要素は、"reading" という言葉で表されています。アプリケーションは、まず入力ストリームから最新の読み取り値を取得します。 そこから、アプリケーションは、最新の読み取り値を定期的に継続して取得するか、または隣接する読み取り値を調べながら入力ストリーム内を前方または後方に走査することができます。 どちらの場合も、通常アプリケーションは、目的の読み取り値間の差異を比較した後で適切なアクションを実行します。
たとえば一人称視点のシューティング ゲームでは、プレイヤーの武器を発砲するかどうかを判断するために、場合によっては各フレームの開始時にボタンが押されたかどうかのみを把握する必要があります。 その場合、重要なのは最新の読み取り値だけです (中間の読み取り値は無視できます)。 これに対して対戦型戦闘ゲームでは、次のいずれかの理由により、最終フレームと現在のフレームの間に発生した入力状態の変化をすべて調べることが必要になる場合があります。
- ボタンのダブルタップが、シングル タップとは別のコンボ/動作にマッピングされる可能性がある。
- 2 つのボタンが押された順序が重要となる場合がある。
- 2 つのボタンが押される間の経過時間が重要となる場合がある。
アプリケーションは、入力ストリームから読み取り値を取得するときに、特定の入力の種類 (ゲームパッドやキーボードなど) からの読み取り値または特定のデバイスからの読み取り値 (あるいはその両方) のみに結果を絞り込むオプションのフィルターを適用できます。 詳細については、「GameInput の読み取り値」を参照してください。
アプリケーションが要求できる入力ストリームからの過去の読み取り値は、直近の 0.5 秒以内に発生したもののみです。 接続されている各デバイスからの最新の読み取り値は、経過時間に関係なく常にアクセス可能です。
インターフェイス
GameInput API は、以下の図に示されているように、グラフィックス API や オーディオ API と同様に、関連するインターフェイスのコレクションを通じて公開されます。
GameInput API サーフェスの大部分を構成する、3 つの主要なインターフェイスがあります。
IGameInput
は、GameInputCreate
ファクトリ関数の呼び出しによって取得される基本インターフェイスです。 これには、入力ストリームから読み取り値を取得するためのメソッド、コールバックを登録するためのメソッド、その他のグローバルな機能にアクセスするためのメソッドが含まれます。IGameInputReading
は、入力ストリーム内の 1 つの要素を表します。 これには、読み取り値に格納されている入力状態データを取得するためのメソッドと、読み取り値を生成したデバイスにアクセスするためのメソッドが含まれます。 読み取り値は、ストリームの他の読み取り値内を前方/後方に移動するときに、入力ストリーム内の参照ポイントとしても使用されます。IGameInputDevice
は、システムに接続されている 1 つの入力デバイスを表します。 これには、デバイスのプロパティと現在の状態を取得するためのメソッドと、デバイスで触覚フィードバックとフォース フィードバックを制御するためのメソッドが含まれます。 また、低レベルの未加工デバイス I/O を実行するためのメソッドも含まれます。
残りのインターフェイスは特定のコンテキストで使用されます。これについては、「GameInput の高度なトピック」で説明しています。
注意
グラフィックス API やオーディオ API と同様に、GameInput は IUnknown から派生するインターフェイスを公開しますが、真の COM API ではありません。 このスタイルの API は "COM ライト" や "ナノ COM" と呼ばれることもあります。IUnknown は参照カウントとリフレクションに使用されていますが、COM ランタイム インフラストラクチャは GameInput には使用されていません。 具体的に、これは次のことを意味します。
- アプリケーションは、オブジェクトのインスタンスを取得するために
CoInitialize
もCoCreateInstance
も呼び出すことはありません。 - 集約や呼び出し元提供のインターフェイスの実装などの COM 機能はサポートされません。
- プロセスの境界を越えたマーシャリングはサポートされず、またアパートメント/スレッド モデルはありません。 すべてのオブジェクトはアジャイルです。
- IUnknown を介さずにインターフェイス ポインターのオブジェクト ID を直接比較できます。
- メソッドでは
HRESULT
コードを返す必要はありません。多くの場合、これによって関数シグネチャが単純になります。
アプリケーションのフォーカス
本体では、GameInput は、アプリケーションにフォーカスがあるときにのみ、入力をアプリケーションに提供します。 それ以外の場合、返される状態には、ユーザーがデバイスにまったく触れていないかのようにニュートラルまたは "休止" の値が含まれます。 これにより、フォーカスの変更を処理する追加の入力コードが不要になります。
PC では、既定ですべてのプロセスに入力が行われます。 今後、この動作は SetFocusPolicy メソッドを使用して変更できるようになります。
アプリケーションがフォーカスを失うと、デバイスに送信されている触覚フィードバックまたはフォース フィードバックはすべて無効となります。 GameInput API を呼び出して新しいフィードバック状態を設定することはできますが、新しい状態はデバイスに送信されません。 アプリケーションにフォーカスが戻ると、アプリケーションによって要求された最新のフィードバック状態が自動的にデバイスに送信されます。
そのため、アプリケーションはフォーカスを得るときも失うときも、入力または触覚/フォース フィードバックに関連する特別なアクションを実行する必要はありません。 GameInput API がアプリケーションに代わって常に正しい処理を実行します。
注意
GameInput API では、アプリケーションはバックグラウンドでの実行中も、特定の種類の低レベルのデバイス I/O 用にデバイスへの排他的アクセスを一時的に取得できます (詳細については、AcquireExclusiveRawDeviceAccess
メソッドの説明を参照してください)。 ただし、これは出力にのみ適用されます。 アプリケーションにフォーカスがないと、入力はアクセス可能になりません。