A livello di sistema, Android segnala i codici evento dei controller di gioco come codici chiave e valori degli assi Android. Nel gioco, puoi ricevere questi codici e valori e convertirli in azioni in-game specifiche.
Quando i giocatori si connettono fisicamente o accoppiano in modalità wireless un controller di gioco ai propri dispositivi Android, il sistema rileva automaticamente il controller come dispositivo di input e inizia a segnalare i relativi eventi di input. Il gioco può ricevere questi eventi di input implementando i seguenti metodi di callback nell'elemento Activity
attivo o nell'View
attivo (devi implementare i callback per Activity
o View
, ma non per entrambi):
- Da
Activity
:dispatchGenericMotionEvent(android.view. MotionEvent)
Chiamato per elaborare eventi di movimento generici come i movimenti del joystick.
dispatchKeyEvent(android.view.KeyEvent)
Chiamato per elaborare eventi chiave come la pressione o il rilascio di un gamepad o di un pulsante del D-pad.
- Da
View
:onGenericMotionEvent(android.view.MotionEvent)
Chiamato per elaborare eventi di movimento generici come i movimenti del joystick.
onKeyDown(int, android.view.KeyEvent)
Chiamata per elaborare la pressione di un tasto fisico, ad esempio un gamepad o un pulsante del D-pad.
onKeyUp(int, android.view.KeyEvent)
Chiamata per elaborare il rilascio di un tasto fisico, ad esempio un gamepad o un pulsante del D-pad.
L'approccio consigliato prevede l'acquisizione degli eventi dall'oggetto View
specifico con cui interagisce l'utente.
Ispeziona i seguenti oggetti forniti dai callback per ottenere informazioni sul tipo di evento di input ricevuto:
KeyEvent
- Un oggetto che descrive gli eventi del pulsante direzionale (D-pad) e del pulsante del gamepad. Gli eventi chiave sono accompagnati da un
codice chiave che indica il pulsante specifico attivato, ad esempio
DPAD_DOWN
oBUTTON_A
. Puoi ottenere il codice chiave chiamandogetKeyCode()
o dai callback degli eventi chiave comeonKeyDown()
. MotionEvent
- Un oggetto che descrive l'input dei movimenti del joystick e dell'attivatore spalla. Gli eventi di movimento sono accompagnati da un codice di azione e da un insieme di valori dell'asse. Il codice di azione specifica il cambiamento di stato
che si è verificato, ad esempio lo spostamento di un joystick. I valori dell'asse descrivono la posizione e altre proprietà di movimento per un controllo fisico specifico, come
AXIS_X
oAXIS_RTRIGGER
. Puoi ottenere il codice di azione chiamandogetAction()
e il valore dell'asse chiamandogetAxisValue()
.
Questa lezione è incentrata su come gestire l'input dai tipi più comuni di controlli fisici (pulsanti del Gamepad, direzionali e joystick) nella schermata di un gioco implementando i metodi di callback View
e l'elaborazione degli oggetti KeyEvent
e MotionEvent
menzionati sopra.
Verificare che un controller di gioco sia collegato
Quando segnali eventi di input, Android non distingue tra gli eventi provenienti da un controller non di gioco e quelli provenienti da un controller di gioco. Ad esempio, un'azione del touchscreen genera un evento AXIS_X
che rappresenta la coordinata X della superficie touch, mentre un joystick genera un evento AXIS_X
che rappresenta la posizione X del joystick. Se al tuo gioco interessa la gestione dell'input del controller di gioco, devi prima verificare che l'evento di input provenga da un tipo di origine pertinente.
Per verificare che un dispositivo di input collegato sia un controller di gioco, chiama getSources()
per ottenere un campo di bit combinato dei tipi di origini di input supportati sul dispositivo. Puoi quindi verificare se
sono impostati i seguenti campi:
- Un tipo di origine
SOURCE_GAMEPAD
indica che il dispositivo di input ha pulsanti del gamepad (ad esempio,BUTTON_A
). Tieni presente che questo tipo di origine non indica rigorosamente se il controller di gioco è dotato di pulsanti D-pad, anche se la maggior parte dei gamepad in genere ha controlli direzionali. - Il tipo di sorgente
SOURCE_DPAD
indica che il dispositivo di input dispone di pulsanti D-pad (ad esempio,DPAD_UP
). - Un tipo di origine
SOURCE_JOYSTICK
indica che il dispositivo di input ha stick di controllo analogici (ad esempio, un joystick che registra i movimenti lungoAXIS_X
eAXIS_Y
).
Il seguente snippet di codice mostra un metodo helper che consente di verificare se i dispositivi di input collegati sono controller di gioco. In tal caso, il metodo recupera gli ID dispositivo dei controller di gioco. Dopodiché puoi associare ogni ID dispositivo a un giocatore nel gioco ed elaborare separatamente le azioni di gioco per ogni giocatore collegato. Per scoprire di più sul supporto di più controller di gioco connessi contemporaneamente sullo stesso dispositivo Android, consulta l'articolo Supporto di più controller di gioco.
Kotlin
fun getGameControllerIds(): List<Int> { val gameControllerDeviceIds = mutableListOf<Int>() val deviceIds = InputDevice.getDeviceIds() deviceIds.forEach { deviceId -> InputDevice.getDevice(deviceId).apply { // Verify that the device has gamepad buttons, control sticks, or both. if (sources and InputDevice.SOURCE_GAMEPAD == InputDevice.SOURCE_GAMEPAD || sources and InputDevice.SOURCE_JOYSTICK == InputDevice.SOURCE_JOYSTICK) { // This device is a game controller. Store its device ID. gameControllerDeviceIds .takeIf { !it.contains(deviceId) } ?.add(deviceId) } } } return gameControllerDeviceIds }
Java
public ArrayList<Integer> getGameControllerIds() { ArrayList<Integer> gameControllerDeviceIds = new ArrayList<Integer>(); int[] deviceIds = InputDevice.getDeviceIds(); for (int deviceId : deviceIds) { InputDevice dev = InputDevice.getDevice(deviceId); int sources = dev.getSources(); // Verify that the device has gamepad buttons, control sticks, or both. if (((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) || ((sources & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK)) { // This device is a game controller. Store its device ID. if (!gameControllerDeviceIds.contains(deviceId)) { gameControllerDeviceIds.add(deviceId); } } } return gameControllerDeviceIds; }
Potresti anche controllare le singole funzionalità di input supportate da un controller di gioco collegato. Questo potrebbe essere utile, ad esempio, se vuoi che il gioco utilizzi solo l'input dell'insieme di controlli fisici che è in grado di comprendere.
Per rilevare se un codice chiave o un codice dell'asse specifico è supportato da un controller di gioco collegato, utilizza queste tecniche:
- In Android 4.4 (livello API 19) o versioni successive, puoi determinare se un codice chiave è supportato su un controller di gioco collegato chiamando
hasKeys(int...)
. - In Android 3.1 (livello API 12) o versioni successive, puoi trovare tutti gli assi disponibili supportati su un controller di gioco collegato chiamando per la prima volta
getMotionRanges()
. Quindi, su ogniInputDevice.MotionRange
oggetto restituito, chiamagetAxis()
per ottenere il suo ID asse.
Pressione dei pulsanti del gamepad
La Figura 1 mostra in che modo Android mappa i codici chiave e i valori degli assi ai controlli fisici sulla maggior parte dei controller di gioco.
![](https://developer.android.google.cn/static/images/training/game-controller-profiles.png?authuser=6&hl=it)
Figura 1. Profilo per un controller di gioco generico.
I callout nella figura si riferiscono a quanto segue:
I codici chiave comuni generati dalla pressione dei pulsanti del gamepad includono
BUTTON_A
,
BUTTON_B
,
BUTTON_SELECT
e BUTTON_START
. Alcuni controller di gioco attivano anche il codice tasto DPAD_CENTER
quando viene premuto il centro della barra trasversale del D-pad. Il tuo
gioco può esaminare il codice chiave chiamando getKeyCode()
o dai callback di eventi chiave come
onKeyDown()
e, se rappresenta un evento pertinente per il tuo gioco, elaborarlo come
azione di gioco. Nella tabella 1 sono elencate le azioni di gioco consigliate per i pulsanti più comuni del gamepad.
Tabella 1. Azioni di gioco consigliate per i pulsanti del gamepad.
Azione di gioco | Codice chiave pulsante |
---|---|
Avvia il gioco nel menu principale oppure mettilo in pausa/riattiva durante il gioco | BUTTON_START * |
Visualizza menu | BUTTON_SELECT *
e KEYCODE_MENU * |
Lo stesso comportamento della navigazione Indietro di Android descritto nella Guida alla progettazione di Navigazione. | KEYCODE_BACK |
Tornare a un elemento precedente in un menu | BUTTON_B |
Conferma la selezione o esegui l'azione principale del gioco | BUTTON_A e
DPAD_CENTER |
* Il gioco non deve fare affidamento sulla presenza dei pulsanti Start, Seleziona o Menu.
Suggerimento: valuta la possibilità di fornire una schermata di configurazione nel gioco per consentire agli utenti di personalizzare le proprie mappature dei controller per le azioni di gioco.
Lo snippet seguente mostra come eseguire l'override di onKeyDown()
per associare le pressioni dei pulsanti BUTTON_A
e DPAD_CENTER
a un'azione di gioco.
Kotlin
class GameView(...) : View(...) { ... override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean { var handled = false if (event.source and InputDevice.SOURCE_GAMEPAD == InputDevice.SOURCE_GAMEPAD) { if (event.repeatCount == 0) { when (keyCode) { // Handle gamepad and D-pad button presses to navigate the ship ... else -> { keyCode.takeIf { isFireKey(it) }?.run { // Update the ship object to fire lasers ... handled = true } } } } if (handled) { return true } } return super.onKeyDown(keyCode, event) } // Here we treat Button_A and DPAD_CENTER as the primary action // keys for the game. private fun isFireKey(keyCode: Int): Boolean = keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_BUTTON_A }
Java
public class GameView extends View { ... @Override public boolean onKeyDown(int keyCode, KeyEvent event) { boolean handled = false; if ((event.getSource() & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) { if (event.getRepeatCount() == 0) { switch (keyCode) { // Handle gamepad and D-pad button presses to // navigate the ship ... default: if (isFireKey(keyCode)) { // Update the ship object to fire lasers ... handled = true; } break; } } if (handled) { return true; } } return super.onKeyDown(keyCode, event); } private static boolean isFireKey(int keyCode) { // Here we treat Button_A and DPAD_CENTER as the primary action // keys for the game. return keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_BUTTON_A; } }
Nota: su Android 4.2 (livello API 17) e versioni precedenti, il sistema considera BUTTON_A
come tasto Indietro di Android per impostazione predefinita. Se la tua app supporta queste versioni di Android, assicurati di considerare BUTTON_A
come azione principale del gioco. Per determinare la versione attuale dell'SDK Android sul dispositivo, fai riferimento al valore Build.VERSION.SDK_INT
.
Elabora input pad direzionale
Il D-pad a 4 vie è un controllo fisico comune in molti controller di gioco. Android segnala le pressioni dei tasti SU e GIÙ del D-pad come
eventi AXIS_HAT_Y
con un intervallo
da -1,0 (su) a 1,0 (giù), mentre le pressioni SINISTRA o DESTRA
del D-pad come
AXIS_HAT_X
eventi con un intervallo da -1,0
(sinistra) a 1,0 (destra).
Alcuni controller invece segnalano le pressioni del D-pad con un codice tasto. Se al tuo gioco interessano le pressioni del D-pad, devi trattare gli eventi dell'asse del cappello e i codici dei tasti del D-pad come gli stessi eventi di input, come consigliato nella tabella 2.
Tabella 2. Azioni di gioco predefinite consigliate per i codici chiave del D-pad e i valori dell'asse dei cappelli.
Azione di gioco | Codice tasto D-pad | Codice asse cappello |
---|---|---|
Sposta su | KEYCODE_DPAD_UP |
AXIS_HAT_Y (per valori da 0 a -1,0) |
Sposta giù | KEYCODE_DPAD_DOWN |
AXIS_HAT_Y (per valori da 0 a 1,0) |
Sposta a sinistra | KEYCODE_DPAD_LEFT |
AXIS_HAT_X (per valori da 0 a -1,0) |
Sposta a destra | KEYCODE_DPAD_RIGHT |
AXIS_HAT_X (per valori da 0 a 1,0) |
Il seguente snippet di codice mostra una classe helper che consente di controllare i valori dell'asse cappello e del codice chiave di un evento di input per determinare la direzione del D-pad.
Kotlin
class Dpad { private var directionPressed = -1 // initialized to -1 fun getDirectionPressed(event: InputEvent): Int { if (!isDpadDevice(event)) { return -1 } // If the input event is a MotionEvent, check its hat axis values. (event as? MotionEvent)?.apply { // Use the hat axis value to find the D-pad direction val xaxis: Float = event.getAxisValue(MotionEvent.AXIS_HAT_X) val yaxis: Float = event.getAxisValue(MotionEvent.AXIS_HAT_Y) directionPressed = when { // Check if the AXIS_HAT_X value is -1 or 1, and set the D-pad // LEFT and RIGHT direction accordingly. xaxis.compareTo(-1.0f) == 0 -> Dpad.LEFT xaxis.compareTo(1.0f) == 0 -> Dpad.RIGHT // Check if the AXIS_HAT_Y value is -1 or 1, and set the D-pad // UP and DOWN direction accordingly. yaxis.compareTo(-1.0f) == 0 -> Dpad.UP yaxis.compareTo(1.0f) == 0 -> Dpad.DOWN else -> directionPressed } } // If the input event is a KeyEvent, check its key code. (event as? KeyEvent)?.apply { // Use the key code to find the D-pad direction. directionPressed = when(event.keyCode) { KeyEvent.KEYCODE_DPAD_LEFT -> Dpad.LEFT KeyEvent.KEYCODE_DPAD_RIGHT -> Dpad.RIGHT KeyEvent.KEYCODE_DPAD_UP -> Dpad.UP KeyEvent.KEYCODE_DPAD_DOWN -> Dpad.DOWN KeyEvent.KEYCODE_DPAD_CENTER -> Dpad.CENTER else -> directionPressed } } return directionPressed } companion object { internal const val UP = 0 internal const val LEFT = 1 internal const val RIGHT = 2 internal const val DOWN = 3 internal const val CENTER = 4 fun isDpadDevice(event: InputEvent): Boolean = // Check that input comes from a device with directional pads. event.source and InputDevice.SOURCE_DPAD != InputDevice.SOURCE_DPAD } }
Java
public class Dpad { final static int UP = 0; final static int LEFT = 1; final static int RIGHT = 2; final static int DOWN = 3; final static int CENTER = 4; int directionPressed = -1; // initialized to -1 public int getDirectionPressed(InputEvent event) { if (!isDpadDevice(event)) { return -1; } // If the input event is a MotionEvent, check its hat axis values. if (event instanceof MotionEvent) { // Use the hat axis value to find the D-pad direction MotionEvent motionEvent = (MotionEvent) event; float xaxis = motionEvent.getAxisValue(MotionEvent.AXIS_HAT_X); float yaxis = motionEvent.getAxisValue(MotionEvent.AXIS_HAT_Y); // Check if the AXIS_HAT_X value is -1 or 1, and set the D-pad // LEFT and RIGHT direction accordingly. if (Float.compare(xaxis, -1.0f) == 0) { directionPressed = Dpad.LEFT; } else if (Float.compare(xaxis, 1.0f) == 0) { directionPressed = Dpad.RIGHT; } // Check if the AXIS_HAT_Y value is -1 or 1, and set the D-pad // UP and DOWN direction accordingly. else if (Float.compare(yaxis, -1.0f) == 0) { directionPressed = Dpad.UP; } else if (Float.compare(yaxis, 1.0f) == 0) { directionPressed = Dpad.DOWN; } } // If the input event is a KeyEvent, check its key code. else if (event instanceof KeyEvent) { // Use the key code to find the D-pad direction. KeyEvent keyEvent = (KeyEvent) event; if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_LEFT) { directionPressed = Dpad.LEFT; } else if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_RIGHT) { directionPressed = Dpad.RIGHT; } else if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_UP) { directionPressed = Dpad.UP; } else if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_DOWN) { directionPressed = Dpad.DOWN; } else if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_CENTER) { directionPressed = Dpad.CENTER; } } return directionPressed; } public static boolean isDpadDevice(InputEvent event) { // Check that input comes from a device with directional pads. if ((event.getSource() & InputDevice.SOURCE_DPAD) != InputDevice.SOURCE_DPAD) { return true; } else { return false; } } }
Puoi utilizzare questa classe helper nel tuo gioco ogni volta che vuoi elaborare l'input del D-pad (ad esempio, nei callback onGenericMotionEvent()
o onKeyDown()
).
Ecco alcuni esempi:
Kotlin
private val dpad = Dpad() ... override fun onGenericMotionEvent(event: MotionEvent): Boolean { if (Dpad.isDpadDevice(event)) { when (dpad.getDirectionPressed(event)) { Dpad.LEFT -> { // Do something for LEFT direction press ... return true } Dpad.RIGHT -> { // Do something for RIGHT direction press ... return true } Dpad.UP -> { // Do something for UP direction press ... return true } ... } } // Check if this event is from a joystick movement and process accordingly. ... }
Java
Dpad dpad = new Dpad(); ... @Override public boolean onGenericMotionEvent(MotionEvent event) { // Check if this event if from a D-pad and process accordingly. if (Dpad.isDpadDevice(event)) { int press = dpad.getDirectionPressed(event); switch (press) { case LEFT: // Do something for LEFT direction press ... return true; case RIGHT: // Do something for RIGHT direction press ... return true; case UP: // Do something for UP direction press ... return true; ... } } // Check if this event is from a joystick movement and process accordingly. ... }
Elabora i movimenti del joystick
Quando i giocatori muovono un joystick sui controller di gioco, Android segnala un
MotionEvent
contenente il
codice di azione ACTION_MOVE
e le posizioni
aggiornate degli assi del joystick. Il gioco può utilizzare i dati forniti da MotionEvent
per determinare se si è verificato un movimento del joystick che gli interessa.
Tieni presente che gli eventi di movimento del joystick possono raggruppare più campioni di movimento all'interno di un singolo oggetto. L'oggetto MotionEvent
contiene la posizione corrente di ogni asse del joystick e più posizioni cronologiche per ogni asse. Quando segnali eventi di movimento con codice di azione ACTION_MOVE
(ad esempio i movimenti del joystick), Android raggruppa i valori dell'asse per migliorare l'efficienza. I valori storici di un asse sono costituiti dall'insieme di valori distinti precedenti al valore dell'asse attuale e più recenti rispetto ai valori riportati in eventi di movimento precedenti. Consulta il riferimento MotionEvent
per i dettagli.
Puoi utilizzare i dati storici per eseguire il rendering più accurato del movimento di un oggetto di gioco in base all'input del joystick. Per recuperare i valori attuali e storici, chiama getAxisValue()
o getHistoricalAxisValue()
. Puoi anche trovare il numero di punti
cronologici nell'evento joystick chiamando
getHistorySize()
.
Lo snippet seguente mostra come eseguire l'override del callback onGenericMotionEvent()
per elaborare l'input del joystick. Devi prima elaborare i valori storici di un asse, quindi elaborarne la posizione attuale.
Kotlin
class GameView(...) : View(...) { override fun onGenericMotionEvent(event: MotionEvent): Boolean { // Check that the event came from a game controller return if (event.source and InputDevice.SOURCE_JOYSTICK == InputDevice.SOURCE_JOYSTICK && event.action == MotionEvent.ACTION_MOVE) { // Process the movements starting from the // earliest historical position in the batch (0 until event.historySize).forEach { i -> // Process the event at historical position i processJoystickInput(event, i) } // Process the current movement sample in the batch (position -1) processJoystickInput(event, -1) true } else { super.onGenericMotionEvent(event) } } }
Java
public class GameView extends View { @Override public boolean onGenericMotionEvent(MotionEvent event) { // Check that the event came from a game controller if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK && event.getAction() == MotionEvent.ACTION_MOVE) { // Process all historical movement samples in the batch final int historySize = event.getHistorySize(); // Process the movements starting from the // earliest historical position in the batch for (int i = 0; i < historySize; i++) { // Process the event at historical position i processJoystickInput(event, i); } // Process the current movement sample in the batch (position -1) processJoystickInput(event, -1); return true; } return super.onGenericMotionEvent(event); } }
Prima di utilizzare l'input del joystick, devi determinare se il joystick è centrato, quindi calcolare i movimenti degli assi di conseguenza. In genere i joystick hanno un'area piatta, ovvero un intervallo di valori vicino alla coordinata (0,0) su cui l'asse è considerato centrato. Se il valore dell'asse riportato da Android rientra nell'area piatta, devi trattare il controller come inattivo, ovvero fermo su entrambi gli assi.
Lo snippet riportato di seguito mostra un metodo helper che calcola il movimento lungo ogni asse. Richiamo questo helper nel metodo processJoystickInput()
descritto più avanti.
Kotlin
private fun getCenteredAxis( event: MotionEvent, device: InputDevice, axis: Int, historyPos: Int ): Float { val range: InputDevice.MotionRange? = device.getMotionRange(axis, event.source) // A joystick at rest does not always report an absolute position of // (0,0). Use the getFlat() method to determine the range of values // bounding the joystick axis center. range?.apply { val value: Float = if (historyPos < 0) { event.getAxisValue(axis) } else { event.getHistoricalAxisValue(axis, historyPos) } // Ignore axis values that are within the 'flat' region of the // joystick axis center. if (Math.abs(value) > flat) { return value } } return 0f }
Java
private static float getCenteredAxis(MotionEvent event, InputDevice device, int axis, int historyPos) { final InputDevice.MotionRange range = device.getMotionRange(axis, event.getSource()); // A joystick at rest does not always report an absolute position of // (0,0). Use the getFlat() method to determine the range of values // bounding the joystick axis center. if (range != null) { final float flat = range.getFlat(); final float value = historyPos < 0 ? event.getAxisValue(axis): event.getHistoricalAxisValue(axis, historyPos); // Ignore axis values that are within the 'flat' region of the // joystick axis center. if (Math.abs(value) > flat) { return value; } } return 0; }
Riassumendo, ecco come potresti elaborare i movimenti del joystick nel gioco:
Kotlin
private fun processJoystickInput(event: MotionEvent, historyPos: Int) { val inputDevice = event.device // Calculate the horizontal distance to move by // using the input value from one of these physical controls: // the left control stick, hat axis, or the right control stick. var x: Float = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_X, historyPos) if (x == 0f) { x = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_HAT_X, historyPos) } if (x == 0f) { x = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_Z, historyPos) } // Calculate the vertical distance to move by // using the input value from one of these physical controls: // the left control stick, hat switch, or the right control stick. var y: Float = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_Y, historyPos) if (y == 0f) { y = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_HAT_Y, historyPos) } if (y == 0f) { y = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_RZ, historyPos) } // Update the ship object based on the new x and y values }
Java
private void processJoystickInput(MotionEvent event, int historyPos) { InputDevice inputDevice = event.getDevice(); // Calculate the horizontal distance to move by // using the input value from one of these physical controls: // the left control stick, hat axis, or the right control stick. float x = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_X, historyPos); if (x == 0) { x = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_HAT_X, historyPos); } if (x == 0) { x = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_Z, historyPos); } // Calculate the vertical distance to move by // using the input value from one of these physical controls: // the left control stick, hat switch, or the right control stick. float y = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_Y, historyPos); if (y == 0) { y = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_HAT_Y, historyPos); } if (y == 0) { y = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_RZ, historyPos); } // Update the ship object based on the new x and y values }
Per supportare controller di gioco con funzionalità più sofisticate oltre a un singolo joystick, segui queste best practice:
- Impugna le levette con doppio controller. Molti controller di gioco
hanno sia un joystick sinistro che quello destro. Per la levetta sinistra, Android
registra i movimenti orizzontali come eventi
AXIS_X
e i movimenti verticali come eventiAXIS_Y
. Per la levetta destra, Android segnala i movimenti orizzontali come eventiAXIS_Z
e i movimenti verticali come eventiAXIS_RZ
. Assicurati di gestire entrambi i controller nel codice. - Gestisci le pressioni dei trigger spalla (ma fornisci metodi di immissione alternativi). Alcuni controller hanno attivatori a sinistra e a destra. Se questi attivatori sono presenti, Android segnala una pressione dell'attivatore sinistro come evento
AXIS_LTRIGGER
e una pressione del trigger a destra come eventoAXIS_RTRIGGER
. Su Android 4.3 (livello API 18), un controller che produce unAXIS_LTRIGGER
segnala anche un valore identico per l'asseAXIS_BRAKE
. Lo stesso vale perAXIS_RTRIGGER
eAXIS_GAS
. Android segnala tutte le pressioni dei trigger analogici con un valore normalizzato compreso tra 0,0 (rilasciato) e 1,0 (completamente premuto). Non tutti i controller hanno attivatori, quindi valuta la possibilità di consentire ai giocatori di eseguire queste azioni di gioco con altri pulsanti.