支援多個遊戲控制器

儘管大多數遊戲都設計為使用單一 Android 裝置支援單一使用者。 系統也能為多個使用者 並同時連線到同一部 Android 裝置。

本課程介紹了處理單張輸入資料 從多個連線控制器中操控多款裝置的多人遊戲。這包括 玩家顯示圖片和每個控制器裝置會保持對應 妥善處理控制器輸入事件

將玩家對應至控制器裝置 ID

當遊戲控制器連線至 Android 裝置時,系統 為該版本指派一個整數的裝置 ID您可以取得已連結 呼叫 InputDevice.getDeviceIds() 來呼叫遊戲控制器,如「確認遊戲控制器已連線」一節中所述。這樣就可以將每個 遊戲中玩家專用的裝置 ID,系統會分別處理每位玩家的遊戲動作。

注意: 在搭載 Android 4.1 (API) 的裝置上 16 級) 以上版本,則可以使用 getDescriptor():傳回不重複的 輸入裝置的永久字串值。與裝置 ID 不同 值不會改變,即使輸入裝置已中斷連線、重新連線或 重新設定。

下列程式碼片段說明如何使用 SparseArray 將玩家的顯示圖片與特定控制器建立關聯。在這個範例中, mShips 變數會儲存 Ship 物件的集合。新的 當使用者附加新控制器時,系統會在遊戲中建立玩家顯示圖片。 並在相關聯的控制器移除時移除。

onInputDeviceAdded()onInputDeviceRemoved() 回呼 方法均屬於 支援所有 Android 版本的控制器。導入這些 事件監聽器回呼,遊戲就能識別遊戲控制器的裝置 ID, 系統就會新增或移除控制器這項偵測功能與 Android 2.3 相容 (API 級別 9) 以上版本。

Kotlin

private val ships = SparseArray<Ship>()

override fun onInputDeviceAdded(deviceId: Int) {
    getShipForID(deviceId)
}

override fun onInputDeviceRemoved(deviceId: Int) {
    removeShipForID(deviceId)
}

private fun getShipForID(shipID: Int): Ship {
    return ships.get(shipID) ?: Ship().also {
        ships.append(shipID, it)
    }
}

private fun removeShipForID(shipID: Int) {
    ships.remove(shipID)
}

Java

private final SparseArray<Ship> ships = new SparseArray<Ship>();

@Override
public void onInputDeviceAdded(int deviceId) {
    getShipForID(deviceId);
}

@Override
public void onInputDeviceRemoved(int deviceId) {
    removeShipForID(deviceId);
}

private Ship getShipForID(int shipID) {
    Ship currentShip = ships.get(shipID);
    if ( null == currentShip ) {
        currentShip = new Ship();
        ships.append(shipID, currentShip);
    }
    return currentShip;
}

private void removeShipForID(int shipID) {
    ships.remove(shipID);
}

處理多個控制器輸入內容

遊戲應執行下列迴圈來處理 多個控制器的輸入:

  1. 偵測輸入事件是否發生。
  2. 識別輸入來源及其裝置 ID。
  3. 根據輸入事件按鍵碼或軸值指定的動作。 更新與該裝置 ID 相關聯的玩家顯示圖片。
  4. 轉譯及更新使用者介面。

KeyEventMotionEvent 輸入來源 事件都有相關聯的裝置 ID。您的遊戲可利用 以便判斷輸入事件來自哪個控制器,並更新 與該控制器相關聯的玩家顯示圖片。

下列程式碼片段顯示如何取得玩家顯示圖片參照 對應遊戲控制器裝置 ID,並根據 使用者的按鈕。

Kotlin

override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
    if (event.source and InputDevice.SOURCE_GAMEPAD == InputDevice.SOURCE_GAMEPAD) {
        event.deviceId.takeIf { it != -1 }?.also { deviceId ->
            val currentShip: Ship = getShipForID(deviceId)
            // Based on which key was pressed, update the player avatar
            // (e.g. set the ship headings or fire lasers)
            return true
        }
    }
    return super.onKeyDown(keyCode, event)
}

Java

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if ((event.getSource() & InputDevice.SOURCE_GAMEPAD)
                == InputDevice.SOURCE_GAMEPAD) {
        int deviceId = event.getDeviceId();
        if (deviceId != -1) {
            Ship currentShip = getShipForId(deviceId);
            // Based on which key was pressed, update the player avatar
            // (e.g. set the ship headings or fire lasers)
            ...
            return true;
        }
    }
    return super.onKeyDown(keyCode, event);
}

注意: 最佳做法是 遊戲控制器中斷連線,建議您暫停遊戲,並詢問使用者是否 想要重新連線。