> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# XInput から GameInput への移植

> XInput から GameInput への移植

<a id="introductionSection" />

XInput から GameInput への移植は、他のどのレガシー API からの移植よりも複雑ではありません。これは、GameInput が XInput のシンプルで (使いやすい) プログラミングモデルから大きな影響を受けており、そのため多くの XInput API が GameInput の同等の関数に 1:1 でマッピングされるためです。

<a id="keyDifferencesSection" />

## 主な違い

XInput と GameInput の主な違いについては、以下のセクションで説明します。

<a id="cVsCppSection" />

### C と C++

XInput API はフラットな C 関数の集合です。一方、GameInput は C++ で、(グラフィックスやオーディオ API と同様に) インターフェイスを使用します。実際には、これにより GameInput API を使用するコードが複雑になることはなく、パフォーマンスにも影響を与えません。また、GameInput の動作に慣れてくると明らかになるいくつかの利点があります。

これらのインターフェイスは COM のように見えるかもしれませんが、そうではないことを理解することが重要です。これらのインターフェイスを使用するには、参照カウントの基本的な理解のみが必要です。詳細については、[GameInput の基礎](/build/core-features/common/input/overviews/input-fundamentals#interfacesSection) トピックの「インターフェイス」セクションを参照してください。

<a id="gettingInputSection" />

### 入力の取得

XInput では、ほとんどのゲームは、接続されたデバイスを持つものが見つかるまでユーザーインデックスをループし、そのデバイスから状態を読み取ります。ゲームは次回ループしなくてもいいように、ユーザーインデックスを覚えておくことがよくあります。たとえば、次のコードは、ユーザーにコントローラーで「A を押してください」と促すゲームで典型的なものです。

```c++ theme={null}
// This function looks for a gamepad that currently has the "A" button pressed.
void FindActiveGamepad()
{
    for (DWORD index = 0; index < XUSER_MAX_COUNT; index++)
    {
        XINPUT_STATE state;
        if (XInputGetState(index, &state) == ERROR_SUCCESS)
        {
            if (state.Gamepad.wButtons & XINPUT_GAMEPAD_A)
            {
                // Found the user's gamepad at this index.
            }
        }
    }
}
```

GameInput では、まずデバイスを指定せずに入力を取得し、必要に応じて入力元のデバイスをクエリできます。コードは似ていますが、明示的なデバイス列挙の必要性を排除することで、よりシンプルなアルゴリズムを実現できます。

```c++ theme={null}
// This function looks for a gamepad that currently has the "A" button pressed.
void FindActiveGamepad(IGameInput * gameInput)
{
    // This checks for input from all gamepads simultaneously.
    IGameInputReading * reading;
    if (SUCCEEDED(gameInput->GetCurrentReading(GameInputKindGamepad, nullptr, &reading)))
    {
        GameInputGamepadState state;
        reading->GetGamepadState(&state);

        if (state.buttons & GameInputGamepadA)
        {
            // Found the user's gamepad.  At this point we can
            // get the device that generated this input, and then
            // pass that into future calls to the GetCurrentReading
            // method to receive input only from that gamepad.
        }

        reading->Release():
    }
}
```

コードは XInput ほどシンプルではありませんが、非常に似ています。GameInput API に慣れてくると、このモデルが XInput には存在しない、入力を処理する強力なオプションを提供することがわかります。

なお、XInput はトリガーからのアナログ値を **BYTE** 型として、サムスティックからのアナログ値を **SHORT** 型として返します。GameInput API では、これらのアナログ値は 0 から 1 (トリガー) または -1 から 1 (サムスティック) の **float** 値として返されます。

<a id="rumbleFeedbackSection" />

### ランブルフィードバック

XInput では、ゲームは単に `XInputSetState` を呼び出してデバイスにランブル (振動) コマンドを送信します。GameInput では、ゲームはデバイスの [IGameInputDevice](/reference/input/gameinput/interfaces/igameinputdevice/igameinputdevice) インスタンスを取得し、その [SetRumbleState](/reference/input/gameinput/interfaces/igameinputdevice/methods/igameinputdevice_setrumblestate) メソッドを呼び出す必要があります。これら 2 つのメソッドの使用法は似ています。これは、デバイスインターフェイスが単なるデバイス識別子であるのではなく、その関数を呼び出す場合の例です。

<a id="appFocusSection" />

### アプリケーションのフォーカス

コンソールでは、GameInput はアプリケーションがフォーカスされているときにのみ入力を提供します。それ以外の場合、返される状態は、ユーザーがデバイスにまったく触れていないかのように、ニュートラルまたは「rest」の値を含みます。これにより、フォーカスの変化に対処する余分な入力コード (たとえば、`XInputEnable` を呼び出すなど) が不要になります。

PC では、入力は既定ではすべてのプロセスに送られます。将来的には、この動作は [SetFocusPolicy](/reference/input/gameinput/interfaces/igameinput/methods/igameinput_setfocuspolicy) メソッドを使用して変更可能になります。

<a id="xinputWrapperSection" />

## XInputOnGameInput ラッパー

Microsoft Game Development Kit (GDK) には `XInputOnGameInput.h` というヘッダーファイルが同梱されており、GameInput 上での XInput API の実装が含まれています。特にキーボードとマウスまたはその他の入力デバイスが必要な場合は、GameInput に直接移植することをお勧めします。ただし、XInputOnGameInput ラッパーは、既存の XInput コードに変更を必要とせずに、初期の移植作業をブートストラップするのに役立つ可能性があります。

XInputOnGameInput ラッパーを使用するには、次のコードを:

```c++ theme={null}
#include <XInput.h>
```

このコードに置き換えます:

```c++ theme={null}
#include <XInputOnGameInput.h>
using namespace XInputOnGameInput;
```

そしてコードを再コンパイルします。

XInput ラッパーコードの実装は完全にヘッダーファイル内にあるため、GameInput API の使用例として調べたり、必要に応じて変更したりすることもできます。

<a id="wrapperDifferencesSection" />

### XInput と XInputOnGameInput の違い

一般に、XInputOnGameInput ラッパーはレガシー XInput API の直接的なドロップイン置換です。ただし、いくつかの小さな違いがあります。

* 簡潔さのために、ラッパーにはゲームパッドデバイスのサポートのみがコード化されています。レーシングホイールやアーケードスティックなど、他のデバイスをサポートする必要がある場合は、GameInput を直接使用するか、XInputOnGameInput コードにこれらのデバイスのサポートを追加してください。

* ラッパーは、ゲームがフォーカスされているときにのみゲームパッド入力を返します。ゲームがフォーカスされていない場合、返されるすべてのゲームパッドの状態は、ユーザーがゲームパッドに触れていないかのように、ニュートラルまたは「rest」値に設定されます。これは、`XInputEnable` への呼び出しの有無に関係なく行われます。

* `XUSER_MAX_COUNT` の値は 4 から 8 に増加されました。これは通常、ほとんどのレガシー XInput コードに対して透過的である必要があります。ただし、コード内での `XInputGetKeystroke` 関数の使用を慎重にレビューし、`XINPUT_KEYSTROKE` 構造体の `UserIndex` メンバーで返される最大値が 4 であることを前提としてハードコードされているものがないことを確認してください。そうしないと、バッファオーバーランが発生する可能性があります。

* いくつかの新しい関数が追加されました (下記参照)。これらは、本番コードで XInput ラッパーを引き続き使用する予定の場合にのみ関心があるはずです。

<a id="productionWrapperUseSection" />

### 本番コードでの 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](/reference/input/gameinput/interfaces/igameinput/igameinput) の [FindDeviceFromId](/reference/input/gameinput/interfaces/igameinput/methods/igameinput_finddevicefromid) メソッドに渡すと、そのユーザーインデックスに対応する [IGameInputDevice](/reference/input/gameinput/interfaces/igameinputdevice/igameinputdevice) が返されます。これを使用すると、XInput ラッパー経由では公開されていない GameInput API の追加機能にアクセスできます。

<a id="optimizingSection" />

#### ラッパーコードの最適化

既定では、XInputOnGameInput ラッパーはレガシー XInput API とドロップイン互換になるように構成されています。100% 互換の動作を必要としないゲームは、次のプリプロセッサマクロのいずれかを定義することで、ラッパーの動作とパフォーマンスを微調整できます。

##### XINPUT\_ON\_GAMEINPUT\_EXPLICIT\_INITIALIZATION

既定では、XInput ラッパーは、ラッパー関数のいずれかが最初に呼び出されるときに、基盤となる GameInput API を自動的に遅延初期化します。これにより既存の XInput コードとのドロップイン互換性が保証されますが、いくつかの小さな欠点があります。

1. 最初の XInput ラッパー関数呼び出しの実行時間は、通常よりも長くなります。

2. すべての XInput ラッパー関数は、呼び出されるたびに遅延初期化が実行されたかどうかをチェックする必要があります。これはグローバル変数の単純なテストなので、分岐予測子がコストを軽減するはずですが、余分なオーバーヘッドです。

3. 失敗することは決してないはずですが、基盤となる GameInput API の遅延初期化が成功したかどうかを判断する方法はありません。

4. 基盤となる [IGameInput](/reference/input/gameinput/interfaces/igameinput/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 ラッパーのコード/データサイズをわずかに減らすことができます。

<a id="seeAlsoSection" />

## リファレンス API ドキュメント

* [GameInput (API 内容)](/reference/input/gameinput/gameinput_members)
* [XInputOnGameInput (API 内容)](/reference/input/xinputongameinput/xinputongameinput_members)

## 関連項目

[GameInput の概要](/build/core-features/common/input/overviews/input-overview)

[GameInput API リファレンス](/reference/input/gc-reference-input-toc)

[Microsoft Game Development Kit](/services/playfab/sdks/platforms/gdk)


## Related topics

- [XInputOnGameInput](/ja-jp/reference/input/xinputongameinput/xinputongameinput_members.md)
- [既存の入力コードを GameInput に移植する](/ja-jp/build/core-features/common/input/porting/index.md)
- [XINPUT_KEYSTROKE](/ja-jp/reference/input/xinputongameinput/structs/xinput_keystroke.md)
- [XINPUT_STATE](/ja-jp/reference/input/xinputongameinput/structs/xinput_state.md)
- [XInputOnGameInputInitialize](/ja-jp/reference/input/xinputongameinput/functions/xinputongameinputinitialize.md)
