雖然大多數遊戲的設計都是支援每部 Android 裝置一位使用者,但您也可以支援多位使用者,只要在同一部 Android 裝置上同時連線多個遊戲控制器即可。
本課程將介紹一些基本技巧,說明如何處理單一裝置多人遊戲中多個連線控制器的輸入。這包括維護玩家虛擬化身與每個控制器裝置之間的對應,以及適當處理控制器輸入事件。
將玩家對應至控制器裝置 ID
遊戲控制器連上 Android 裝置時,系統會指派整數裝置 ID。您可以呼叫 InputDevice.getDeviceIds(),取得已連線遊戲控制器的裝置 ID,如「確認遊戲控制器已連線」所示。然後將每個裝置 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);
}
處理多個控制器的輸入內容
遊戲應執行下列迴圈,處理多個控制器的輸入內容:
- 偵測是否發生輸入事件。
- 找出輸入來源及其裝置 ID。
- 根據輸入事件鍵碼或軸值所指出的動作,更新與該裝置 ID 相關聯的玩家虛擬人偶。
- 算繪及更新使用者介面。
KeyEvent 和 MotionEvent 輸入事件會與裝置 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);
}