Android 支持多個(gè)游戲控制器

2018-08-02 18:23 更新

編寫(xiě):heray1990 - 原文:http://developer.android.com/training/game-controllers/multiple-controllers.html

盡管大部分的游戲都被設(shè)計(jì)成一臺(tái) Android 設(shè)備支持一個(gè)用戶(hù),但是仍然有可能支持在同一臺(tái) Android 設(shè)備上同時(shí)連接的多個(gè)游戲控制器(即多個(gè)用戶(hù))。

這節(jié)課覆蓋了一些處理單個(gè)設(shè)備多個(gè)玩家(或者多個(gè)控制器)輸入的基本技術(shù)。這包括維護(hù)一個(gè)在玩家化身和每個(gè)控制器之間的映射,以及適當(dāng)?shù)靥幚砜刂破鞯妮斎胧录?/p>

映射玩家到控制器的設(shè)備 ID

當(dāng)一個(gè)游戲控制器連接到一臺(tái) Android 設(shè)備,系統(tǒng)會(huì)為控制器指定一個(gè)整型的設(shè)備 ID。我們可以通過(guò)調(diào)用 InputDevice.getDeviceIds() 來(lái)取得已連接的游戲控制器的設(shè)備 ID,如驗(yàn)證游戲控制器是否已連接介紹的一樣。我們可以將每個(gè)設(shè)備 ID 與游戲中的玩家關(guān)聯(lián)起來(lái),然后分別處理每個(gè)玩家的游戲動(dòng)作。

Note:在運(yùn)行著 Android 4.1(API level 16)或者更高版本的設(shè)備上,我們可以通過(guò)使用 getDescriptor() 來(lái)取得輸入設(shè)備的描述符。上述函數(shù)為輸入設(shè)備返回一個(gè)唯一連續(xù)的字符串值。不同于設(shè)備 ID,即使在輸入設(shè)備斷開(kāi)、重連或者重新配置時(shí),描述符都不會(huì)變化。

下面的代碼介紹了如何使用 SparseArray 來(lái)關(guān)聯(lián)玩家化身與一個(gè)特定的控制器。在這個(gè)例子中,mShips 變量保存了一個(gè) Ship 對(duì)象的集合。當(dāng)一個(gè)新的控制器連接到一個(gè)用戶(hù)時(shí),會(huì)創(chuàng)建一個(gè)新的玩家化身。當(dāng)已關(guān)聯(lián)的控制器被移除時(shí),對(duì)應(yīng)的玩家化身會(huì)被移除。

onInputDeviceAdded() 和 onInputDeviceRemoved() 回調(diào)函數(shù)是在不同的 Android 系統(tǒng)版本支持控制器中介紹的抽象層的一部分。通過(guò)實(shí)現(xiàn)這些 listener 回調(diào),我們的游戲可以在添加或者移除控制器的時(shí)候,識(shí)別出游戲控制器的設(shè)備 ID。這個(gè)檢測(cè)兼容 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);
}

處理多個(gè)控制器輸入

我們的游戲應(yīng)該執(zhí)行下面的循環(huán)來(lái)處理多個(gè)控制器的輸入:

  1. 檢測(cè)是否出現(xiàn)一個(gè)輸入事件。

  2. 識(shí)別輸入源和它的設(shè)備 ID。

  3. 根據(jù)以輸入事件按鍵碼或者坐標(biāo)值的形式表示的 action,更新玩家化身與設(shè)備 ID 的關(guān)聯(lián)關(guān)系。

  4. 渲染和更新用戶(hù)界面。

keyEvent 和 MotionEvent 輸入事件與設(shè)備 ID 相關(guān)聯(lián)。我們的游戲可以利用這個(gè)關(guān)聯(lián)來(lái)確定輸入事件從哪個(gè)控制器發(fā)出,并且更新玩家化身與控制器的關(guān)聯(lián)。

下面的代碼介紹了我們?nèi)绾螌⒁粋€(gè)玩家化身引用相應(yīng)的游戲控制器設(shè)備 ID,并且根據(jù)用戶(hù)按下控制器的按鍵來(lái)更新游戲。

@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:一個(gè)最佳做法,當(dāng)用戶(hù)的游戲控制器斷開(kāi)時(shí),我們應(yīng)該停止游戲并詢(xún)問(wèn)用戶(hù)是否像要重新連接。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)