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 connessi contemporaneamente sullo stesso dispositivo Android.
Questa lezione riguarda alcune tecniche di base per la gestione dell'input nei gioco multiplayer sul dispositivo da più controller collegati. Sono inclusi mantenere una mappatura tra gli avatar dei giocatori e ogni controller e degli eventi di input del controller in modo appropriato.
Mappare i player agli ID dispositivo del controller
Quando un controller di gioco è collegato a un dispositivo Android, il sistema
gli assegna un ID dispositivo intero. Puoi ottenere gli ID dispositivo per dispositivi connessi
chiamata InputDevice.getDeviceIds()
, come mostrato nella sezione Verificare che un controller di gioco sia connesso. Puoi quindi associare ogni
ID dispositivo con un giocatore nel gioco ed elabora le azioni di gioco per ogni giocatore separatamente.
Nota: sui dispositivi con Android 4.1 (API
livello 16) e superiore, puoi ottenere il descrittore di un dispositivo di input utilizzando
getDescriptor()
, che restituisce un valore
valore di stringa permanente per il dispositivo di input. A differenza di un ID dispositivo, il descrittore
non cambierà anche se il dispositivo di input è scollegato, ricollegato o
riconfigurate.
Lo snippet di codice riportato di seguito mostra come utilizzare un SparseArray
per associare l'avatar di un giocatore a un controller specifico. In questo esempio,
La variabile mShips
archivia una raccolta di Ship
oggetti. Un nuovo
l'avatar del giocatore viene creato in-game quando un utente collega un nuovo controller
e quando viene rimosso il controller associato.
Il callback onInputDeviceAdded()
e onInputDeviceRemoved()
fanno parte dello strato di astrazione introdotto
.
Supporto di controller su tutte le versioni di Android. Implementando questi
di ascolto, il gioco può identificare l'ID dispositivo del controller di gioco quando
viene aggiunto o rimosso. Questo rilevamento è compatibile con Android 2.3
(livello API 9) e superiori.
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); }
Elabora input di più controller
Il gioco deve eseguire il seguente loop per elaborare input da più controller:
- Rileva se si è verificato un evento di input.
- Identifica l'origine di input e il relativo ID dispositivo.
- In base all'azione indicata dal codice chiave dell'evento di input o dal valore dell'asse, aggiornare l'avatar del player associato a quell'ID dispositivo.
- Esegui il rendering e aggiorna l'interfaccia utente.
Input di KeyEvent
e MotionEvent
sono associati a un ID dispositivo. Il tuo gioco può sfruttare
questo 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 potresti ottenere un riferimento per l'avatar di un player corrispondente all'ID dispositivo di un controller di gioco e aggiorna il gioco in base al premere il pulsante dell'utente su quel 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); }
Nota : come best practice, quando un utente il controller di gioco si disconnette, devi mettere in pausa il gioco e chiedere se l'utente vuole riconnettersi.