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 d'accepter plusieurs utilisateurs avec des manettes de jeu connectées simultanément sur le même appareil Android.

Cette leçon présente quelques techniques de base pour gérer les entrées d'un jeu multijoueur sur un seul appareil à partir de plusieurs manettes connectées. Cela inclut le maintien d'un mappage entre les avatars des joueurs et chaque manette, et le traitement approprié des événements d'entrée de la manette.

Mapper les joueurs à des ID de manettes

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 d'appareils 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 dans votre jeu et traiter les actions de chaque joueur séparément.

Remarque : Sur les appareils équipés d'Android 4.1 (niveau d'API 16) ou version ultérieure, vous pouvez obtenir le descripteur d'un appareil d'entrée à l'aide de getDescriptor(), qui renvoie une valeur de chaîne persistante unique pour le périphérique d'entrée. Contrairement à un ID d'appareil, la valeur du descripteur ne change pas, même si le périphérique d'entrée est déconnecté, reconnecté ou reconfiguré.

L'extrait de code ci-dessous montre comment utiliser un 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 avatar de joueur est créé lorsqu'une nouvelle manette est associée par un utilisateur, puis supprimé lorsque la manette associée est supprimée.

Les méthodes de rappel onInputDeviceAdded() et onInputDeviceRemoved() font partie de la couche d'abstraction introduite dans Prendre en charge les contrôleurs dans les versions d'Android. En implémentant ces rappels d'écouteur, votre jeu peut identifier l'ID d'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) ou version ultérieure.

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 plusieurs entrées de manette

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

  1. Détecter si un événement d'entrée s'est produit.
  2. Identifiez la source d'entrée et son ID d'appareil.
  3. En fonction de l'action indiquée par le code de touche d'événement d'entrée ou la valeur d'axe, 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 la manette d'où 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 mettre à jour le jeu en fonction de la pression sur le bouton de l'utilisateur sur 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);
}

Remarque : Lorsque la manette de jeu d'un utilisateur se déconnecte, vous devez mettre le jeu en pause et lui demander s'il souhaite se reconnecter.