編寫:heray1990 - 原文:http://developer.android.com/training/game-controllers/multiple-controllers.html
盡管大部分的游戲都被設(shè)計成一臺 Android 設(shè)備支持一個用戶,但是仍然有可能支持在同一臺 Android 設(shè)備上同時連接的多個游戲控制器(即多個用戶)。
這節(jié)課覆蓋了一些處理單個設(shè)備多個玩家(或者多個控制器)輸入的基本技術(shù)。這包括維護一個在玩家化身和每個控制器之間的映射,以及適當?shù)靥幚砜刂破鞯妮斎胧录?/p>
當一個游戲控制器連接到一臺 Android 設(shè)備,系統(tǒng)會為控制器指定一個整型的設(shè)備 ID。我們可以通過調(diào)用 InputDevice.getDeviceIds()
來取得已連接的游戲控制器的設(shè)備 ID,如驗證游戲控制器是否已連接介紹的一樣。我們可以將每個設(shè)備 ID 與游戲中的玩家關(guān)聯(lián)起來,然后分別處理每個玩家的游戲動作。
Note:在運行著 Android 4.1(API level 16)或者更高版本的設(shè)備上,我們可以通過使用
getDescriptor()
來取得輸入設(shè)備的描述符。上述函數(shù)為輸入設(shè)備返回一個唯一連續(xù)的字符串值。不同于設(shè)備 ID,即使在輸入設(shè)備斷開、重連或者重新配置時,描述符都不會變化。
下面的代碼介紹了如何使用 SparseArray 來關(guān)聯(lián)玩家化身與一個特定的控制器。在這個例子中,mShips
變量保存了一個 Ship
對象的集合。當一個新的控制器連接到一個用戶時,會創(chuàng)建一個新的玩家化身。當已關(guān)聯(lián)的控制器被移除時,對應(yīng)的玩家化身會被移除。
onInputDeviceAdded()
和 onInputDeviceRemoved()
回調(diào)函數(shù)是在不同的 Android 系統(tǒng)版本支持控制器中介紹的抽象層的一部分。通過實現(xiàn)這些 listener 回調(diào),我們的游戲可以在添加或者移除控制器的時候,識別出游戲控制器的設(shè)備 ID。這個檢測兼容 Android 2.3(API level 9)和更高的版本。
private final SparseArray<Ship> mShips = 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 = mShips.get(shipID);
if ( null == currentShip ) {
currentShip = new Ship();
mShips.append(shipID, currentShip);
}
return currentShip;
}
private void removeShipForID(int shipID) {
mShips.remove(shipID);
}
我們的游戲應(yīng)該執(zhí)行下面的循環(huán)來處理多個控制器的輸入:
檢測是否出現(xiàn)一個輸入事件。
識別輸入源和它的設(shè)備 ID。
根據(jù)以輸入事件按鍵碼或者坐標值的形式表示的 action,更新玩家化身與設(shè)備 ID 的關(guān)聯(lián)關(guān)系。
keyEvent 和 MotionEvent 輸入事件與設(shè)備 ID 相關(guān)聯(lián)。我們的游戲可以利用這個關(guān)聯(lián)來確定輸入事件從哪個控制器發(fā)出,并且更新玩家化身與控制器的關(guān)聯(lián)。
下面的代碼介紹了我們?nèi)绾螌⒁粋€玩家化身引用相應(yīng)的游戲控制器設(shè)備 ID,并且根據(jù)用戶按下控制器的按鍵來更新游戲。
@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);
}
Note:一個最佳做法,當用戶的游戲控制器斷開時,我們應(yīng)該停止游戲并詢問用戶是否像要重新連接。