Assurer la compatibilité avec plusieurs manettes de jeu

Bien que la plupart des jeux soient conçus pour prendre en charge un seul utilisateur par appareil Android, il est également possible de prendre en charge plusieurs utilisateurs avec des manettes de jeu connectées simultanément sur le même appareil Android.

Cette leçon aborde quelques techniques de base pour gérer les entrées dans votre jeu multijoueur sur un seul appareil à partir de plusieurs manettes connectées. Cela inclut la gestion d'un mappage entre les avatars des joueurs et chaque périphérique de contrôle, ainsi que le traitement approprié des événements d'entrée du contrôle.

Mappez les joueurs aux ID de périphérique de la manette.

Lorsqu'une manette de jeu est connectée à un appareil Android, le système lui attribue un ID d'appareil entier. Vous pouvez obtenir les ID des manettes de jeu connectées en appelant InputDevice.getDeviceIds(), comme indiqué dans Vérifier qu'une manette de jeu est connectée. Vous pouvez ensuite associer chaque ID d'appareil à un joueur de votre jeu et traiter les actions de jeu pour chaque joueur séparément.

L'extrait de code montre comment utiliser SparseArray pour associer l'avatar d'un joueur à une manette spécifique. Dans cet exemple, la variable mShips stocke une collection d'objets Ship. Un nouvel avatar de joueur est créé dans le jeu lorsqu'un utilisateur connecte une nouvelle manette, et supprimé lorsque la manette associée est déconnectée.

Les méthodes de rappel onInputDeviceAdded() et onInputDeviceRemoved() font partie de la couche d'abstraction introduite dans Assurer la compatibilité avec des manettes de jeu dans différentes versions d'Android. En implémentant ces rappels d'écouteur, votre jeu peut identifier l'ID de l'appareil de la manette de jeu lorsqu'une manette est ajoutée ou supprimée. Cette détection est compatible avec Android 2.3 (niveau d'API 9) et versions ultérieures.

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

Traiter les entrées de plusieurs manettes

Votre jeu doit exécuter la boucle suivante pour traiter les entrées de plusieurs manettes :

  1. Détectez si un événement d'entrée s'est produit.
  2. Identifiez la source d'entrée et l'ID de l'appareil.
  3. En fonction de l'action indiquée par le code de touche ou la valeur d'axe de l'événement d'entrée, mettez à jour l'avatar du joueur associé à cet ID d'appareil.
  4. Afficher et mettre à jour l'interface utilisateur.

Les événements d'entrée KeyEvent et MotionEvent sont associés à des ID d'appareil. Votre jeu peut en profiter pour déterminer de quelle manette provient l'événement d'entrée et mettre à jour l'avatar du joueur associé à cette manette.

L'extrait de code suivant montre comment obtenir une référence d'avatar de joueur correspondant à un ID d'appareil de manette de jeu et comment mettre à jour le jeu en fonction de l'appui de l'utilisateur sur un bouton de cette manette.

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