Anche se la maggior parte dei giochi è progettata per supportare un singolo utente per dispositivo Android, è anche possibile supportare più utenti con controller di gioco collegati contemporaneamente allo stesso dispositivo Android.
Questa lezione tratta alcune tecniche di base per la gestione dell'input nel gioco multiplayer per un singolo dispositivo da più controller connessi. Ciò include il mantenimento di una mappatura tra gli avatar dei giocatori e ogni dispositivo di controllo e l'elaborazione appropriata degli eventi di input del controller.
Mappare i giocatori agli ID dispositivo del controller
Quando un controller di gioco è connesso a un dispositivo Android, il sistema
gli assegna un ID dispositivo intero. Puoi ottenere gli ID dispositivo per i controller
di gioco connessi chiamando InputDevice.getDeviceIds(), come mostrato in
Verificare che un controller sia connesso. Puoi quindi associare ogni ID dispositivo a un giocatore nel tuo gioco ed elaborare le azioni di gioco per ogni giocatore separatamente.
Il frammento di codice mostra come utilizzare un SparseArray per associare l'avatar di un giocatore a un controller specifico. In questo esempio, la variabile mShips
memorizza una raccolta di oggetti Ship. Quando un utente collega un nuovo controller, viene creato un nuovo avatar del giocatore nel gioco e viene rimosso quando viene rimosso il controller associato.
I metodi di callback onInputDeviceAdded() e onInputDeviceRemoved()
fanno parte del livello di astrazione introdotto in Supporto dei controller in
tutte le versioni di Android.
Implementando questi callback del listener, il gioco può identificare l'ID dispositivo del controller di gioco quando un controller viene aggiunto o rimosso. Questo rilevamento
è compatibile con Android 2.3 (livello API 9) e versioni successive.
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);
}
Elaborare l'input di più controller
Il gioco deve eseguire il seguente ciclo per elaborare l'input da più controller:
- Rileva se si è verificato un evento di input.
- Identifica la sorgente di ingresso e il relativo ID dispositivo.
- In base all'azione indicata dal codice chiave dell'evento di input o dal valore dell'asse, aggiorna l'avatar del giocatore associato all'ID dispositivo.
- Esegui il rendering e aggiorna l'interfaccia utente.
Gli eventi di input KeyEvent e MotionEvent
hanno ID dispositivo
associati. Il gioco può sfruttare questa funzionalità per determinare da quale
controller proviene l'evento di input e aggiornare l'avatar del giocatore associato
a quel controller.
Il seguente snippet di codice mostra come ottenere un riferimento all'avatar di un giocatore corrispondente a un ID dispositivo di un controller di gioco e aggiornare il gioco in base alla pressione del pulsante dell'utente sul controller.
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);
}