Unterstützung für mehrere Gamecontroller

Die meisten Spiele sind so konzipiert, dass sie einen einzelnen Nutzer pro Android-Gerät unterstützen. Es ist aber auch möglich, mehrere Nutzer mit Controllern zu unterstützen, die gleichzeitig mit demselben Android-Gerät verbunden sind.

In dieser Lektion werden einige grundlegende Techniken für die Verarbeitung von Eingaben in einem Mehrspielerspiel mit mehreren verbundenen Controllern beschrieben. Dazu gehört die Aufrechterhaltung einer Zuordnung zwischen den Spieleravataren und den einzelnen Controller-Geräten sowie die entsprechende Verarbeitung von Controller-Eingabeereignissen.

Spieler den Controller-Geräte-IDs zuordnen

Wenn ein Gamecontroller mit einem Android-Gerät verbunden ist, weist das System ihm eine ganzzahlige Geräte-ID zu. Du kannst die Geräte-IDs für verbundene Game-Controller abrufen, indem du InputDevice.getDeviceIds() aufrufst, wie unter Prüfen, ob ein Gamecontroller verbunden ist. Anschließend können Sie jede Geräte-ID einem Spieler in Ihrem Spiel zuordnen und Spielaktionen für jeden Spieler separat verarbeiten.

Hinweis : Auf Geräten mit Android 4.1 (API-Ebene 16) und höher können Sie den Deskriptor eines Eingabegeräts mithilfe von getDescriptor() abrufen. Dieser gibt einen eindeutigen, persistenten Stringwert für das Eingabegerät zurück. Im Gegensatz zu einer Geräte-ID ändert sich der Deskriptorwert auch dann nicht, wenn das Eingabegerät getrennt, wieder verbunden oder neu konfiguriert wird.

Das folgende Code-Snippet zeigt, wie du mit einem SparseArray den Avatar eines Spielers mit einem bestimmten Controller verknüpfen kannst. In diesem Beispiel speichert die Variable mShips eine Sammlung von Ship-Objekten. Ein neuer Spieleravatar wird im Spiel erstellt, wenn ein Nutzer einen neuen Controller hinzufügt, und entfernt, wenn der zugehörige Controller entfernt wird.

Die Callback-Methoden onInputDeviceAdded() und onInputDeviceRemoved() sind Teil der Abstraktionsebene, die unter Controller für Android-Versionen unterstützen vorgestellt wurde. Durch die Implementierung dieser Listener-Callbacks kann Ihr Spiel die Geräte-ID des Game-Controllers identifizieren, wenn ein Controller hinzugefügt oder entfernt wird. Diese Erkennung ist mit Android 2.3 (API-Level 9) und höher kompatibel.

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);
}

Eingabe mehrerer Controller verarbeiten

Ihr Spiel sollte die folgende Schleife ausführen, um Eingaben von mehreren Controllern zu verarbeiten:

  1. Erkennt, ob ein Eingabeereignis aufgetreten ist.
  2. Identifizieren Sie die Eingabequelle und die Geräte-ID.
  3. Aktualisiere den mit dieser Geräte-ID verknüpften Spieleravatar basierend auf der Aktion, die durch den Eingabeereignis-Schlüsselcode oder den Achsenwert angegeben wird.
  4. Rendern und aktualisieren Sie die Benutzeroberfläche.

KeyEvent- und MotionEvent-Eingabeereignissen sind Geräte-IDs zugeordnet. Ihr Spiel kann diese Funktion nutzen, um zu ermitteln, von welchem Controller das Eingabeereignis stammt, und den mit diesem Controller verknüpften Spieleravatar aktualisieren.

Das folgende Code-Snippet zeigt, wie Sie einen Spieleravatar-Verweis abrufen, der einer Spiele-Controller-Geräte-ID entspricht, und das Spiel basierend auf dem Drücken der Nutzertaste auf diesem Controller aktualisieren können.

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);
}

Hinweis : Wenn der Gamecontroller eines Nutzers getrennt wird, sollten Sie als Best Practice das Spiel anhalten und fragen, ob der Nutzer wieder eine Verbindung herstellen möchte.