Cómo administrar las acciones de los controles

A nivel del sistema, Android informa los códigos de eventos de entrada de controles de 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 o vinculan de forma inalámbrica un control de juego de sus dispositivos con Android, el sistema detecta como dispositivo de entrada y comienza a informar sus eventos de entrada. Tu juego puede recibir estos eventos de entrada implementando los siguientes métodos de devolución de llamada en tu Activity o View enfocado (deberías implementar las devoluciones de llamada para Activity o View, pero no ambos):

El enfoque recomendado es capturar los eventos desde el objeto View específico con el que el usuario interactúa. Inspecciona los siguientes objetos que proporcionan las devoluciones de llamada para obtener información sobre el tipo de evento de entrada recibido:

KeyEvent
Objeto que describe objetivos pad direccional (D-pad) y eventos de botones del mando de juegos. Los eventos clave incluyen un código de tecla que indica el botón específico activado, como DPAD_DOWN o BUTTON_A. Puedes obtener el el código de la tecla llamando a getKeyCode() o desde la tecla de devoluciones de llamada de eventos, onKeyDown()
MotionEvent
Un objeto que describe la entrada del joystick y el gatillo lateral. movimientos. Los eventos de movimiento van acompañados de un código de acción y un conjunto valores de ejes. El código de acción especifica el cambio de estado que se produjo. como mover un joystick. Los valores de los ejes describen la posición y otras propiedades de movimiento para un control físico específico, como AXIS_X o AXIS_RTRIGGER Puedes obtener el código de acción llamando a getAction() y al valor del eje llamando a getAxisValue().

Esta lección se enfoca en cómo manejar las entradas de los tipos más comunes de controles físicos (botones del mando de juegos, mandos de dirección y joysticks) en la pantalla de un juego mediante la implementación de los métodos Métodos de devolución de llamada y procesamiento de View 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 vinieron de un controlador que no era un juego y los eventos que ocurrieron desde un controlador de juegos. Por ejemplo, una acción de pantalla táctil genera una AXIS_X que representa el evento X coordenada de la superficie táctil, pero el joystick genera una Evento AXIS_X que representa la posición X del joystick. Si Si tu juego se preocupa por manejar la entrada de controles de juegos, primero deberías verificar que el evento de entrada provenga de un tipo de fuente relevante.

Para verificar que un dispositivo de entrada conectado es un control de juegos, llama a getSources() para obtener un campo de bits combinado de tipos de entradas de entrada compatibles con ese dispositivo. Luego, puedes probar se configuran los siguientes campos:

  • Un tipo de fuente de SOURCE_GAMEPAD indica que el dispositivo de entrada tenga botones de control de juegos (por ejemplo, BUTTON_A). Ten en cuenta que esta fuente no indica estrictamente si el control de juego 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 registra movimientos a lo largo del AXIS_X y AXIS_Y).

El siguiente fragmento de código muestra un método de ayuda que permite verificar si los dispositivos de entrada conectados son controles de juegos. Si es así, el método recupera los IDs de dispositivo de los controles de juegos. Luego, puedes asociar cada dispositivo ID con un jugador en tu juego y procesa las acciones del juego para cada conexión reproductor independiente. Si quieres obtener más información sobre la compatibilidad con varios controles de juegos que están conectadas simultáneamente en el mismo dispositivo Android, consulta Cómo brindar compatibilidad con varios controles de 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 desees comprobar las capacidades de entrada individuales compatibles con un control de juegos conectado. Esto podría ser útil, por ejemplo, si tu juego solo usará la entrada del conjunto de controles físicos comprendan.

Para detectar si un código de tecla o de eje específico es compatible con un código de eje o controlador de juegos, usa estas técnicas:

  • En Android 4.4 (nivel de API 19) o versiones posteriores, puedes determinar si un código de clave es compatible con un control de juegos conectado llamando hasKeys(int...)
  • En Android 3.1 (nivel de API 12) o versiones posteriores, puedes encontrar todos los ejes disponibles compatible con un control de juegos conectado llamando getMotionRanges() Luego, en cada Se muestra un objeto InputDevice.MotionRange, llama getAxis() 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 la ubicación física de la mayoría de los controles de juegos.

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 el botón del control de mando, se incluyen los siguientes: BUTTON_A, BUTTON_B, BUTTON_SELECT, y BUTTON_START. Un juego los controladores también activan el código de tecla DPAD_CENTER cuando se presiona el centro de la barra del pad direccional. Tu El juego puede inspeccionar el código de tecla llamando a getKeyCode() o desde devoluciones de llamadas de eventos de teclas, como onKeyDown(), y, si representa un evento que es relevante para tu juego, procésalo como un la acción del juego. En la tabla 1, se enumeran las acciones del juego recomendadas para las acciones más comunes botones de control de mando.

Tabla 1: Acciones de juego recomendadas para controles de juegos botones.

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 la navegación hacia atrás de Android descrito en las 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

* El juego no debe depender de la presencia de las opciones Inicio, Seleccionar o Menú. botones.

Sugerencia: Considera proporcionar una pantalla de configuración en tu juego para permitir que los usuarios personalicen sus propias asignaciones de controles de juegos para las acciones del juego.

En el siguiente fragmento, se muestra cómo puedes anular onKeyDown() a asociar el objeto BUTTON_A y Pulsaciones del botón 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 (API nivel 17) y versiones anteriores, el sistema trata BUTTON_A como Android Tecla Atrás de forma predeterminada. Si tu app admite Android de versiones canary, asegúrate de tratar BUTTON_A como juego principal acción. Para determinar el SDK de Android actual, sigue estos pasos: versión en el dispositivo, consulta la 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 juegos controladores. Android informa que las pulsaciones hacia ARRIBA y ABAJO en el pad direccional son AXIS_HAT_Y eventos con un rango de -1.0 (arriba) a 1.0 (abajo), y el pad direccional presiona IZQUIERDA o DERECHA como AXIS_HAT_X eventos 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 tu juego se preocupa por las pulsaciones del pad direccional, deberías tratar los eventos del eje del sombrero y el pad direccional como los mismos eventos de entrada, como se recomienda en la tabla 2.

Tabla 2: Acciones de juego predeterminadas recomendadas para la tecla de pad direccional y valores de eje del pulsador.

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 el sombrero valores de eje y clave de código a partir de 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 procesarla. la entrada de pad direccional (por ejemplo, en el onGenericMotionEvent() o onKeyDown() devoluciones de llamada).

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 un joystick en sus controles de juegos, Android informa un MotionEvent, que contiene lo siguiente: Código de acción de ACTION_MOVE y la actualización de los ejes del joystick. Tu juego puede usar los datos proporcionados por el objeto MotionEvent para determinar si el joystick lo mueve. qué preocupa.

Ten en cuenta que los eventos de movimiento del joystick pueden agrupar varias muestras de movimiento por lotes. dentro de un solo objeto. El objeto MotionEvent contiene la posición actual de cada eje del joystick, además de varios valores posiciones para 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 valores del eje para la eficiencia. Los valores históricos de un eje consisten en los conjunto de valores distintos más antiguos que el valor del eje actual y más recientes que informados en cualquier evento de movimiento anterior. Consulta la MotionEvent para obtener más detalles.

Puedes usar la información histórica para renderizar un juego con mayor precisión el movimiento del objeto basado en la entrada del joystick. Para recuperar los valores actuales e históricos, llamar getAxisValue() o getHistoricalAxisValue(). También puedes encontrar la cantidad de registros puntos en el evento del joystick llamando getHistorySize()

En el siguiente fragmento, se muestra cómo puedes anular el Es la devolución de llamada onGenericMotionEvent() para procesar la entrada del joystick. Primero debes procesar los valores históricos de un eje y, luego, procesar 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 calcular los movimientos de su eje según corresponda. Por lo general, los joysticks Tener un área plana, es decir, un rango de valores cerca de la coordenada (0,0) en el que el eje se considera centrado. Si el valor del eje reportado por Android se encuentra dentro del área plana, debes tratar que el control esté en reposo (es decir, inmóvil en ambos ejes).

El siguiente fragmento muestra un método de ayuda que calcula el movimiento junto con cada eje. Debes 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;
}

Haciendo una revisión general, así es como puedes procesar los movimientos del joystick en tu juego:

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
}

Para admitir controles de juegos que tienen más allá de un solo joystick, sigue estas prácticas recomendadas:

  • Administra los controles de dos sticks. Muchos controles de juegos tienen el joystick izquierdo y el derecho. Para el stick izquierdo, Android Informa los movimientos horizontales como eventos AXIS_X. y movimientos verticales como eventos AXIS_Y. Para el stick derecho, Android informa los movimientos horizontales como AXIS_Z eventos y movimientos verticales como AXIS_RZ eventos. Asegúrate de manejar ambos controles se guardan en el código.
  • Controla las pulsaciones de los gatillos (pero proporciona entradas alternativas) métodos). Algunos controles tienen hombro izquierdo y derecho activadores. Si se encuentran estos activadores, Android informa que se presiona el gatillo izquierdo. como un evento AXIS_LTRIGGER y como presionar el gatillo derecho como AXIS_RTRIGGER evento. En Android 4.3 (nivel de API 18), un controlador que produce un AXIS_LTRIGGER también informa un valor idéntico para el eje AXIS_BRAKE. El lo mismo sucede con AXIS_RTRIGGER y AXIS_GAS Android informa todos los activadores analógicos presiona con un valor normalizado de 0.0 (liberado) a 1.0 (completamente presionado). No todos los controladores tienen gatillos, así que permite que los jugadores acciones del juego con otros botones.