GameController API(廃止)


GameController API(廃止)

Amazon Fire TVデバイスでは、最大7つのBluetoothコントローラーを同時にシステムに接続できます。したがって、マルチプレーヤーのアプリやゲームを開発することができます。コントローラーを識別して入力イベントを管理するには、InputDeviceクラスと標準のAndroidイベントハンドラー(onKeyUp()onKeyDown()またはonGenericMotionEvent())が含まれた標準のAndroidメカニズムを使用します。

以前のFire TVプラットフォームには、ゲームコントローラーの入力管理をサポートするカスタムAPIが含まれていました。Fire OS 5では、このGameController APIが廃止され、将来的にはプラットフォームから削除されます。アプリでGameController APIを使用している場合は、代わりに標準のAndroid(Lollipop、API 22)InputDeviceAPIの使用に移行することを強くお勧めします。

このドキュメントでは、廃止されたGameController APIから標準のAndroid入力デバイスAPIにコードを移行する方法について説明します。

コントローラーとプレーヤー番号

GameController APIは主に、プレーヤー番号と接続済みコントローラーを関連付けるために使用されます。この動作の大半は、標準のAndroidInputDeviceクラスでgetControllerNumber()メソッドを使用して実現できます。

各コントローラーには、Amazon Fire TVに接続されるときに一意の番号が割り当てられます。この番号は、コントローラーの接続が切断され、再度接続されると、変更される可能性があります。

リモコンなど、ゲームコントローラー以外の入力デバイス(具体的にはInputDevice.SOURCE_GAMEPADまたはInputDevice.SOURCE_JOYSTICKで指定されていない入力デバイス)には、コントローラー番号として0が割り当てられます。

Amazon GameController APIからの移行

Fire OSでは、Fire TV GameController APIの呼び出しが以前と同じように機能しますが、GameController APIは廃止されており、将来的にはプラットフォームから削除されます。現在アプリでGameController APIを使用している場合は、標準のAndroid入力デバイス管理を使用するようにコードを移行することを強くお勧めします

GameController APIからアプリを移行するには、次の手順に従います。

  • com.amazon.device.gamecontrollerパッケージを含め、GameControllerクラスに対するリファレンスをすべて削除します。
  • onCreate()メソッドからGameController.init()を削除します。
  • プレーヤーIDを取得するためのGameControllerメソッドをAndroidInputDevice.getControllerNumber()に置き換えます。
  • 下表のとおり、GameControllerイベント定数を、標準のAndroid KeyEvent定数またはMotionEvent定数に置き換えます。
GameController入力定数 Androidキーまたはモーションイベント定数
GameController.AXIS_STICK_LEFT_X MotionEvent.AXIS_Y
GameController.AXIS_STICK_LEFT_Y MotionEvent.AXIS_Y
GameController.AXIS_STICK_RIGHT_X MotionEvent.AXIS_Z
GameController.AXIS_STICK_RIGHT_Y MotionEvent.AXIS_RZ
GameController.AXIS_TRIGGER_LEFT MotionEvent.AXIS_BRAKE
GameController.AXIS_TRIGGER_RIGHT MotionEvent.AXIS_GAS
GameController.BUTTON_A KeyEvent.KEYCODE_BUTTON_A
GameController.BUTTON_B KeyEvent.KEYCODE_BUTTON_B
GameController.BUTTON_X KeyEvent.KEYCODE_BUTTON_X
GameController.BUTTON_Y KeyEvent.KEYCODE_BUTTON_Y
GameController.BUTTON_SHOULDER_LEFT KeyEvent.KEYCODE_BUTTON_L1
GameController.BUTTON_SHOULDER_RIGHT KeyEvent.KEYCODE_BUTTON_R1
GameController.BUTTON_TRIGGER_LEFT KeyEvent.KEYCODE_BUTTON_L2
GameController.BUTTON_TRIGGER_RIGHT KeyEvent.KEYCODE_BUTTON_R2
GameController.BUTTON_STICK_LEFT KeyEvent.KEYCODE_BUTTON_THUMBL
GameController.BUTTON_STICK_RIGHT KeyEvent.KEYCODE_BUTTON_THUMBR
GameController.BUTTON_DPAD_UP KeyEvent.KEYCODE_DPAD_UP
GameController.BUTTON_DPAD_DOWN KeyEvent.KEYCODE_DPAD_DOWN
GameController.BUTTON_DPAD_LEFT KeyEvent.KEYCODE_DPAD_LEFT
GameController.BUTTON_DPAD_RIGHT KeyEvent.KEYCODE_DPAD_RIGHT
GameController.BUTTON_DPAD_CENTER KeyEvent.KEYCODE_DPAD_CENTER
GameController.BUTTON_AXIS_HAT_X MotionEvent.AXIS_HAT_X
GameController.BUTTON_AXIS_HAT_Y MotionEvent.AXIS_HAT_Y

GameController APIのプレーヤー番号(廃止)

1台のAmazon Fire TVデバイスにはBluetoothゲームコントローラーを7台まで接続できますが、プレーヤー番号に割り当てられるのはそのうちの4台だけです。コントローラーはプレーヤー番号スロットに割り当てられるため、個々のコントローラーが切断されても採番され直すことはありません。つまり、プレーヤー番号は連番にはなりません。

GameController APIには、使用可能なゲームコントローラーのプレーヤー番号にアクセスするためのメソッドが含まれています。5人以上のプレーヤーで遊べるゲームの場合は、ゲーム内のコントローラーとプレーヤー番号を自分で管理することもできます。

デバイスIDによるプレーヤー番号の取得

GameController.getPlayerNumber()静的メソッドにAndroidデバイスIDを指定して呼び出すと、そのデバイスのプレーヤー番号を取得できます。AndroidデバイスIDは、InputDevice.getDeviceIDs()メソッドを使用して、任意のキーイベントやモーションイベント(InputEvent.getDeviceId())から取得できます。あるいは、GameController.getDeviceID()を使用してプレーヤー番号から取得することもできます。

プレーヤー番号はシステム全体で定義されます。一部のデバイスIDはプレーヤー番号に関連付けられていないことがあります。この場合、getPlayerNumber()PlayerNumberNotFoundException例外をスローします。

int[] ids = InputDevice.getDeviceIds();

for (int i=0; i < ids.length; i++) {
    try {
       int playerNum = GameController.getPlayerNumber(ids[i]);
    }   catch (PlayerNumberNotFoundException e) {
        // ...
    }
    // ...
}

プレーヤー番号によるデバイスIDの取得

GameController.getDeviceID()メソッドはgetPlayerNumber()とは逆に、プレーヤー番号(1~4)を指定して呼び出すとAndroidデバイスIDが返されます。一部のプレーヤー番号はデバイスIDに関連付けられていないことがあります。この場合、GameController.getDeviceID()DeviceNotFoundException例外をスローします。

for (int n = 0; n < GameController.MAX_PLAYERS; n++) {
    try {
        int devicenum = GameController.getDeviceID(n + 1);
    }
    catch (DeviceNotFoundException e) {
        // ...
    }
    // ...
}

プレーヤー番号の取得

GameController.getPlayerCount()静的メソッドを使用すると、使用可能なプレーヤー番号を取得できます。プレーヤー番号は必ずしも連番ではない点に注意してください。たとえば、2人のプレーヤーにスロット2と4が割り当てられることもあります。

int players = GameController.getPlayerCount();

プレーヤーによるGameControllerオブジェクトの取得

GameController.getControllerByPlayer()静的メソッドにプレーヤー番号を指定して呼び出すと、フレームベースのイベント入力に使用するGameControllerブジェクトを取得できます(「フレームベースの入力イベント」を参照)。プレーヤー番号は、システムによって1~4の範囲で割り当てられます。一部のプレーヤー番号はコントローラーに関連付けられていないことがあります。この場合、GameController.getControllerbyPlayer()PlayerNumberNotFoundException例外をスローします。

for (int n = 0; n < GameController.MAX_PLAYERS; n++) {
    GameController gameController = null;
    try {
        gameController =
                GameController.getControllerByPlayer(n + 1);
    }
    catch (PlayerNumberNotFoundException e) {
        // ...
    }
}

GameController APIのフレームベースの入力イベント(廃止)

入力イベントは、コントローラーから標準のAndroidイベント駆動型プログラミングモデルを使用して処理できます。このモデルでは、入力イベントが到着しだい処理されます。GameControllerクラスでは、フレームベースの入力モデルを使用できます。このモデルでは、イベントがキャッシュされ、各フレームを描画する前にコントローラーの状態を問い合わせることができます。このモデルでは、次の手順を使用します。

  1. 独自のゲームループを用意して、標準のAndroidイベントモデルを置き換えます。
  2. 標準の入力イベントをGameControllerに転送します。
  3. ループ内の各フレームについて、次の処理を実行します。
    • プレーヤー入力に対して、各コントローラーの状態を問い合わせます。
    • その入力データを使用してフレームをレンダリングします。

イベントのGameControllerへの転送

GameControllerAPIを使用して入力イベントを管理するには、キーイベントとモーションイベントをGameControllerクラスに転送して処理します。これらのイベントをGameControllerに渡すように、onKeyUp()onKeyDown()onGenericMotionEvent()の各メソッドをオーバーライドしてください。

//状態を管理できるようにKeyDownイベントをGameControllerに転送します
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    boolean handled = false;
    try {
        handled = GameController.onKeyDown(keyCode, event);
    }
    catch (DeviceNotFoundException e) {
    }
    return handled || super.onKeyDown(keyCode, event);
}
//状態を管理できるようにKeyUpイベントをGameControllerに転送します
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
    boolean handled = false;
    try {
        handled = GameController.onKeyUp(keyCode, event);
    }
    catch (DeviceNotFoundException e) {
    }
    return handled || super.onKeyUp(keyCode, event);
}
//状態を管理できるようにモーションイベントをGameControllerに転送します
@Override
public boolean onGenericMotionEvent(MotionEvent event) {
    boolean handled = false;
    try {
        handled = GameController.onGenericMotionEvent(event);
    }
    catch (DeviceNotFoundException e) {
    }
    return handled || super.onGenericMotionEvent(event);
}

ゲームループの実装

自分のスレッドでゲームループを実装します。そのスレッドのrun()メソッド内で、入力をテストして、その入力に基づいて各フレームをレンダリングします。アクティビティのonPause()メソッドとonResume()メソッドで、忘れずにスレッドの停止と開始を行ってください。

ループ内でGameController.startFrame()を使用して、フレーム間の入力イベントキューをリセットします。簡単な例を挙げると、次のようになります。

while (running){
    GameController.startFrame();

    //バックグラウンドを描画する

    //各プレーヤーを描画する
    for (int n = 0; n GameController.DEAD_ZONE * GameController.DEAD_ZONE){
    //スティックの角度は中心のデッドゾーンより大きい
    x[n] += Math.round(deltaX * 10);
    y[n] += Math.round(deltaY * 10);
}

ボタンの押し下げ

wasButtonPressed()メソッドまたはwasButtonReleased()メソッドを使用すると、最後のフレームの描画以降にボタンの入力が発生したかどうかをテストできます。

if (gameController.wasButtonPressed(GameController.BUTTON_A)
    || gameController.wasButtonPressed(GameController.BUTTON_DPAD_CENTER)){
    // 現在のプレーヤーのx、yの位置に円を描画する
}

isButtonPressed()を使用すると、任意のボタンの現在の状態をテストできます。

//D-Padボタンを押して、プレーヤーの位置を移動する:
x[n] += gameController.isButtonPressed(GameController.BUTTON_DPAD_RIGHT) ? +5 : 0;
x[n] += gameController.isButtonPressed(GameController.BUTTON_DPAD_LEFT) ? -5 : 0;
y[n] += gameController.isButtonPressed(GameController.BUTTON_DPAD_DOWN) ? +5 : 0;
y[n] += gameController.isButtonPressed(GameController.BUTTON_DPAD_UP) ? -5 : 0;

GameController APIのイベント定数(廃止)

GameControllerクラスには、ボタンと軸のイベントタイプを表す静的なイベント定数のセットが含まれています。これらの定数は、KeyEventクラスとMotionEventクラスの標準定数と同じですが、コントローラーにも同じ定数が定義されています。ただし、定数名は通常、より論理的になっています。たとえば、GameController.BUTTON_AKeyEvent.KEYCODE_BUTTON_Aとまったく同じです。これらの定数は、「フレームベースの入力イベント」で説明したフレームベースのコントローラーモデルで使用します。

ゲームコントローラーの操作 アナログ移動:wasAxisChanged() getAxisValue() ボタンの押し下げ:
wasButtonPressed()
wasButtonReleased()
isButtonPressed()
デフォルトの動作(イベントがコードによって処理されない場合)
D-Pad(左/右) AXIS_HAT_X(正の値は右方向を表します) なし ユーザーインターフェイスのフォーカスが特定の方向に移動します。
D-Pad(上/下) AXIS_HAT_Y(正の値は下方向を表します) なし ユーザーインターフェイスのフォーカスが特定の方向に移動します。
左側のジョイスティック(左/右) AXIS_STICK_LEFT_X(正の値は右方向を表します) なし ユーザーインターフェイスのフォーカスが特定の方向に移動します。
左側のジョイスティック(上/下) AXIS_STICK_LEFT_Y(正の値は下方向を表します) なし ユーザーインターフェイスのフォーカスが特定の方向に移動します。
左側のジョイスティックの押し下げ なし BUTTON_STICK_LEFT 何も起こりません。
右側のジョイスティック(左/右) AXIS_STICK_RIGHT_X(正の値は右方向を表します) なし 何も起こりません。
右側のジョイスティック(上/下) AXIS_STICK_RIGHT_Y(正の値は下方向を表します) なし 何も起こりません。
右側のジョイスティックの押し下げ なし BUTTON_STICK_RIGHT 何も起こりません。
A なし BUTTON_A 現在フォーカスがあるアイテムが選択されます。
B なし BUTTON_B 前の画面(アクティビティ)に戻ります([戻る] と同じ)。
X なし BUTTON_X 何も起こりません。
Y なし BUTTON_Y 何も起こりません。
左側のトリガー(L2) AXIS_TRIGGER_LEFT なし 現在フォーカスがあるアイテムが選択されます。
左側のショルダー(L1) なし BUTTON_SHOULDER_LEFT 何も起こりません。
右側のトリガー(R2) AXIS_TRIGGER_RIGHT なし 現在フォーカスがあるアイテムが選択されます。
右側のショルダー(R1) なし BUTTON_SHOULDER_RIGHT 何も起こりません。