A nivel del sistema, Android informa los códigos de eventos de entrada de controles para juegos como códigos de teclas y valores de ejes de Android. En tu juego, puedes recibir estos códigos y valores y convertirlos en acciones específicas dentro del juego.
Cuando los jugadores conectan físicamente un control de juegos o vinculan de forma inalámbrica un control para videojuegos con sus dispositivos Android, el sistema detecta automáticamente el control como un dispositivo de entrada y comienza a informar los eventos de entrada. Tu juego puede recibir estos eventos de entrada implementando los siguientes métodos de devolución de llamada en tu Activity
activo o View
enfocado (debes implementar las devoluciones de llamada para Activity
o View
, pero no para ambos):
- Desde
Activity
:dispatchGenericMotionEvent(android.view. MotionEvent)
Se llama para procesar los eventos de movimiento genéricos, como los movimientos del joystick.
dispatchKeyEvent(android.view.KeyEvent)
Se llama para procesar eventos de tecla, como cuando se presiona o se suelta un botón de un control de juegos o un pad direccional.
- Desde
View
:onGenericMotionEvent(android.view.MotionEvent)
Se llama para procesar los eventos de movimiento genéricos, como los movimientos del joystick.
onKeyDown(int, android.view.KeyEvent)
Se llama para procesar la pulsación de una tecla física, como un botón de un pad direccional o control de juegos.
onKeyUp(int, android.view.KeyEvent)
Se llama para procesar el lanzamiento de una tecla física, como un botón de un pad direccional o control de juegos.
El enfoque recomendado es capturar los eventos desde el objeto View
específico con el que interactúa el usuario.
Inspecciona los siguientes objetos que proporcionan las devoluciones de llamada a fin de obtener información sobre el tipo de evento de entrada recibido:
KeyEvent
- Es un objeto que describe eventos de botones de un mando de dirección (pad direccional) y de un control de juegos. Los eventos de tecla van acompañados de un código de tecla que indica el botón específico activado, como
DPAD_DOWN
oBUTTON_A
. Para obtener el código de tecla, llama agetKeyCode()
o desde devoluciones de llamada de eventos de tecla, comoonKeyDown()
. MotionEvent
- Es un objeto que describe la entrada de los movimientos del joystick y del gatillo lateral. Los eventos de movimiento van acompañados de un código de acción y un conjunto de valores de ejes. El código de acción especifica el cambio de estado que se produjo, por ejemplo, cuando se movió el joystick. Los valores de los ejes describen la posición y otras propiedades de movimiento de un control físico específico, como
AXIS_X
oAXIS_RTRIGGER
. Puedes obtener el código de acción llamando agetAction()
y el valor de los ejes llamando agetAxisValue()
.
Esta lección se centra en cómo puedes procesar la entrada de los tipos de controles físicos más comunes (botones de controles de juegos, mandos de dirección y joysticks) en una pantalla de juego mediante la implementación de los métodos de devolución de llamada View
mencionados anteriormente y el procesamiento de los objetos KeyEvent
y MotionEvent
.
Cómo verificar si un control para videojuegos está conectado
Cuando se informan eventos de entrada, Android no distingue entre los eventos que provienen de un dispositivo que no es un control de juegos y los eventos que provienen de un control de juegos. Por ejemplo, una acción de pantalla táctil genera un evento AXIS_X
que representa la coordenada X de la superficie táctil, pero un joystick genera un evento AXIS_X
que representa la posición X del joystick. Si tu juego se encarga de administrar la entrada de controles para juegos, primero debes verificar que el evento de entrada provenga de un tipo de fuente relevante.
Si deseas verificar que un dispositivo de entrada conectado es un control para videojuegos, llama a getSources()
a fin de obtener un campo de bits combinado de los tipos de fuentes de entrada compatibles con ese dispositivo. Luego, puedes realizar una prueba para ver si se configuraron los siguientes campos:
- Un tipo de fuente de
SOURCE_GAMEPAD
indica que el dispositivo de entrada tiene botones de control de juegos (por ejemplo,BUTTON_A
). Ten en cuenta que este tipo de fuente no indica estrictamente si el control para juegos tiene botones de pad direccional, aunque la mayoría de los controles de juegos suelen tener controles direccionales. - Un tipo de fuente de
SOURCE_DPAD
indica que el dispositivo de entrada tiene botones de pad direccional (por ejemplo,DPAD_UP
). - Un tipo de fuente de
SOURCE_JOYSTICK
indica que el dispositivo de entrada tiene sticks de control analógicos (por ejemplo, un joystick que graba movimientos junto conAXIS_X
yAXIS_Y
).
En el siguiente fragmento de código, se muestra un método auxiliar que te permite comprobar si los dispositivos de entrada conectados son controles para juegos. Si es así, el método recupera los ID de dispositivo de los controles para juegos. Luego, puedes asociar cada ID de dispositivo con un jugador en tu juego y procesar las acciones del juego para cada jugador conectado por separado. Si deseas obtener más información sobre la compatibilidad con varios controles para juegos que se conectan simultáneamente en el mismo dispositivo Android, consulta Cómo brindar compatibilidad con varios controles para juegos.
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; }
Además, es posible que quieras buscar capacidades de entrada individuales compatibles con un control para videojuegos conectado. Esto podría ser útil, por ejemplo, si quieres que tu juego use solo la entrada del conjunto de controles físicos que comprende.
A fin de detectar si un control para juegos conectado admite un código de tecla o un código de eje específicos, usa las siguientes técnicas:
- En Android 4.4 (nivel de API 19) o versiones posteriores, puedes llamar a
hasKeys(int...)
para determinar si un código de tecla es compatible con un control para videojuegos conectado. - En Android 3.1 (nivel de API 12) o versiones posteriores, puedes encontrar todos los ejes disponibles compatibles con un control para juegos conectado si primero llamas a
getMotionRanges()
. Luego, en cada objetoInputDevice.MotionRange
que se muestra, llama agetAxis()
para obtener su ID de eje.
Cómo procesar la presión de los botones del control de juegos
En la Figura 1, se muestra cómo Android asigna códigos de teclas y valores de ejes a los controles físicos de la mayoría de los controles para videojuegos.

Figura 1: Perfil de un control para videojuegos genérico
Las leyendas de la figura hacen referencia a lo siguiente:
Entre los códigos de teclas comunes que se generan cuando se presiona un botón del control de juegos, se incluyen BUTTON_A
, BUTTON_B
, BUTTON_SELECT
y BUTTON_START
. Algunos controles de juego también activan el código de tecla DPAD_CENTER
cuando se presiona el centro de la barra del pad direccional. El juego puede inspeccionar el código de tecla llamando a getKeyCode()
o desde devoluciones de llamada de eventos de tecla, como onKeyDown()
, y, si representa un evento relevante para el juego, procesarlo como una acción del juego. En la tabla 1, se enumeran las acciones del juego recomendadas para los botones de controles de juegos más comunes.
Tabla 1: Acciones de juego recomendadas para los botones del control de juegos
Acción del juego | Código de tecla del botón |
---|---|
Iniciar juego en el menú principal o pausar/reanudar durante el juego | BUTTON_START * |
Mostrar menú | BUTTON_SELECT * y KEYCODE_MENU * |
Igual que el comportamiento de navegación hacia atrás de Android que se describe en la guía de diseño de navegación. | KEYCODE_BACK |
Volver al elemento de menú anterior | BUTTON_B |
Confirmar la selección o realizar una acción principal del juego | BUTTON_A y DPAD_CENTER |
* Tu juego no debería depender de la presencia de los botones Inicio, Seleccionar o Menú.
Sugerencia: Considera proporcionar una pantalla de configuración en tu juego de modo que los usuarios puedan personalizar sus propias asignaciones de controles para videojuegos en las acciones del juego.
En el siguiente fragmento, se muestra cómo puedes anular onKeyDown()
para asociar las pulsaciones de los botones BUTTON_A
y DPAD_CENTER
con una acción del juego.
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: En Android 4.2 (nivel de API 17) y versiones anteriores, el sistema trata a BUTTON_A
como la tecla Atrás de Android de forma predeterminada. Si tu app admite estas versiones de Android, asegúrate de tratar a BUTTON_A
como la acción principal del juego. Para determinar la versión actual del SDK de Android en el dispositivo, consulta el valor Build.VERSION.SDK_INT
.
Cómo procesar la entrada de un pad direccional
El mando de dirección de 4 direcciones (pad direccional) es un control físico común en muchos controles de juegos. Android informa las pulsaciones hacia ARRIBA y ABAJO en el pad direccional como eventos AXIS_HAT_Y
con un rango de -1.0 (arriba) a 1.0 (abajo), y las pulsaciones de las teclas IZQUIERDA o DERECHA en el pad direccional como eventos AXIS_HAT_X
con un rango de -1.0 (izquierda) a 1.0 (derecha).
Sin embargo, algunos controles informan las pulsaciones en el pad direccional con un código de tecla. Si a tu juego le interesan las pulsaciones del pad direccional, debes tratar los eventos de eje del sombrero y los códigos de las teclas de pad direccional como los mismos eventos de entrada, como se recomienda en la tabla 2.
Tabla 2: Acciones de juego predeterminadas recomendadas para los códigos de teclas de pad direccional y valores de ejes de sombrero.
Acción del juego | Código de tecla del pad direccional | Código de eje del pulsador |
---|---|---|
Subir | KEYCODE_DPAD_UP |
AXIS_HAT_Y (para los valores de 0 a -1.0) |
Bajar | KEYCODE_DPAD_DOWN |
AXIS_HAT_Y (para los valores 0 a 1.0) |
Mover hacia la izquierda | KEYCODE_DPAD_LEFT |
AXIS_HAT_X (para los valores de 0 a -1.0) |
Mover hacia la derecha | KEYCODE_DPAD_RIGHT |
AXIS_HAT_X (para los valores 0 a 1.0) |
En el siguiente fragmento de código, se muestra una clase auxiliar que te permite verificar los valores del eje del sombrero y del código de tecla desde un evento de entrada para determinar la dirección del pad direccional.
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; } } }
Puedes usar esta clase auxiliar en tu juego donde quieras procesar la entrada de pad direccional (por ejemplo, en las devoluciones de llamada onGenericMotionEvent()
o onKeyDown()
).
Por ejemplo:
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. ... }
Cómo procesar los movimientos del joystick
Cuando los jugadores mueven el joystick en los controles de juegos, Android informa un MotionEvent
que contiene el código de acción ACTION_MOVE
y las posiciones actualizadas de los ejes del joystick. El juego puede usar los datos que proporciona MotionEvent
para determinar si se produjo un movimiento del joystick que te interesa.
Ten en cuenta que los eventos de movimiento del joystick pueden agrupar varias muestras de movimientos por lotes dentro de un solo objeto. El objeto MotionEvent
contiene la posición actual de cada eje del joystick, así como varias posiciones históricas de cada eje. Cuando se informan eventos de movimiento con el código de acción ACTION_MOVE
(como los movimientos del joystick), Android agrupa por lotes los valores de los ejes para mayor eficiencia. Los valores históricos de un eje consisten en el conjunto de valores distintos anteriores al valor actual del eje y más recientes que los valores informados en cualquier evento de movimiento anterior. Consulta la referencia de MotionEvent
para obtener más detalles.
Puedes usar la información histórica para renderizar con mayor precisión el movimiento de un objeto de juego según la entrada del joystick. Para recuperar los valores históricos y actuales, llama a getAxisValue()
o getHistoricalAxisValue()
. También puedes llamar a getHistorySize()
para buscar la cantidad de puntos históricos en el evento del joystick.
En el siguiente fragmento, se muestra cómo puedes anular la devolución de llamada onGenericMotionEvent()
para procesar la entrada del joystick. Primero, debes procesar los valores históricos de un eje y, luego, su posición actual.
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); } }
Antes de usar la entrada del joystick, debes determinar si está centrado y, luego, calcular los movimientos de sus ejes según corresponda. Los joysticks suelen tener un área plana, es decir, un rango de valores cerca de la coordenada (0,0) en la que se considera que el eje está centrado. Si el valor del eje que informa Android se encuentra dentro del área plana, deberías tratar el control como en reposo (es decir, inactivo en ambos ejes).
En el siguiente fragmento, se muestra un método auxiliar que calcula el movimiento a lo largo de cada eje. Puedes invocar este asistente en el método processJoystickInput()
que se describe más adelante.
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; }
En resumen, puedes procesar los movimientos del joystick en el juego de la siguiente manera:
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 }
Si deseas admitir controles para juegos que tengan funciones más sofisticadas además de un solo joystick, sigue estas prácticas recomendadas:
- Administra los controles de dos sticks. Muchos controles para juegos tienen un joystick izquierdo y uno derecho. En el caso del stick izquierdo, Android informa los movimientos horizontales como eventos
AXIS_X
y los movimientos verticales como eventosAXIS_Y
. En el caso del stick derecho, Android informa los movimientos horizontales como eventosAXIS_Z
y los movimientos verticales como eventosAXIS_RZ
. Asegúrate de controlar los dos sticks del control en tu código. - Controla las pulsaciones de los gatillos (pero proporciona métodos de entrada alternativos). Algunos controles tienen gatillos. Si estos activadores están presentes, Android informa una pulsación del gatillo izquierdo como un evento
AXIS_LTRIGGER
y una pulsación del gatillo derecho como un eventoAXIS_RTRIGGER
. En Android 4.3 (nivel de API 18), un controlador que produce unAXIS_LTRIGGER
también informa un valor idéntico para el ejeAXIS_BRAKE
. Lo mismo sucede conAXIS_RTRIGGER
yAXIS_GAS
. Android informa todas las pulsaciones de activadores analógicos con un valor normalizado de 0.0 (liberado) a 1.0 (completamente presionado). No todos los controles tienen gatillos, así que considera permitir que los jugadores realicen esas acciones del juego con otros botones.