Controlleraktionen verarbeiten

Auf Systemebene meldet Android Eingabeereigniscodes von Gamecontrollern als Android-Schlüsselcodes und Achsenwerte. In Ihrem Spiel können Sie diese Codes empfangen und in bestimmte In-Game-Aktionen umzuwandeln.

Wenn Spieler einen Gamecontroller physisch verbinden oder kabellos damit koppeln erkennt das System den Controller automatisch, und beginnt, die entsprechenden Eingabeereignisse zu melden. Dein Spiel kann Folgendes empfangen: Eingabeereignisse generieren, indem Sie die folgenden Callback-Methoden in Ihren aktiven Activity oder fokussierter View (Sie sollten Implementieren Sie die Callbacks entweder für Activity oder View, aber nicht beides):

Es wird empfohlen, die Ereignisse aus der Bestimmtes View-Objekt, mit dem der Nutzer interagiert Prüfen Sie die folgenden von den Callbacks bereitgestellten Objekte, um Informationen zu erhalten zum Typ des empfangenen Eingabeereignisses:

KeyEvent
Ein Objekt, das direktionale Richtungen beschreibt Tastenereignisse für Gamepads (Steuerkreuz) und Gamepad-Tasten. Schlüsselereignisse werden begleitet von Schlüsselcode, der angibt, welche Schaltfläche ausgelöst wurde, z. B.: DPAD_DOWN oder BUTTON_A. Sie erhalten die durch Aufrufen von getKeyCode() oder über die Taste mit dem Schlüsselcode Ereignis-Callbacks wie onKeyDown().
MotionEvent
Ein Objekt, das die Eingabe über den Joystick und den Schulterauslöser beschreibt Bewegungen. Bewegungsereignisse werden von einem Aktionscode und einer Reihe von Achsenwerte. Der Aktionscode gibt die Statusänderung an, die aufgetreten ist z. B. wenn ein Joystick bewegt wird. Die Achsenwerte beschreiben die Position und andere Bewegungseigenschaften für ein bestimmtes physikalisches Steuerelement, wie AXIS_X oder AXIS_RTRIGGER. Sie können den Aktionscode abrufen, durch Aufrufen von getAction() und den Achsenwert durch getAxisValue() wird angerufen.

In dieser Lektion wird erläutert, wie Sie mit Eingaben aus den gängigsten Arten von physische Bedienelemente (Gamepad-Tasten, Richtungstasten und Joysticks) in einem Spiele-Bildschirm zu platzieren, indem Sie die oben genannten View-Callback-Methoden und -Verarbeitung KeyEvent- und MotionEvent-Objekte.

Prüfen, ob ein Controller verbunden ist

Bei der Berichterstellung von Eingabeereignissen unterscheidet Android nicht zwischen Ereignissen, die nicht von einem Controller-Gerät stammen, und Ereignissen, mit einem Controller. Beispielsweise generiert eine Touchscreen-Aktion ein AXIS_X-Ereignis, das das X darstellt Koordinate der Touchoberfläche. Ein Joystick generiert eine AXIS_X-Ereignis, das die X-Position des Joysticks darstellt. Wenn die Eingabe des Gamecontrollers in deinem Spiel wichtig ist, dass das Eingabeereignis aus einem relevanten Quelltyp stammt.

Um zu überprüfen, ob ein angeschlossenes Eingabegerät ein Gamecontroller ist, rufe folgenden Befehl auf: getSources(), um ein kombiniertes Bitfeld mit Typen von Eingabequellen, die auf diesem Gerät unterstützt werden. Sie können dann testen, sind folgende Felder festgelegt:

  • Der Quelltyp SOURCE_GAMEPAD gibt an, dass das Eingabegerät über Gamepad-Tasten verfügt (z. B. BUTTON_A). Beachten Sie, dass diese Quelle gibt nicht streng an, ob der Controller über Steuerkreuze verfügt, die meisten Gamepads verfügen jedoch in der Regel über eine Steuerrichtung.
  • Der Quelltyp SOURCE_DPAD gibt an, dass das Eingabegerät über Steuerkreuztasten verfügt, z. B. DPAD_UP).
  • Quelltyp SOURCE_JOYSTICK gibt an, dass das Eingabegerät analoge Sticks hat (z. B. ein Joystick, der Bewegungen entlang von AXIS_X aufzeichnet und AXIS_Y).

Das folgende Code-Snippet zeigt eine Hilfsmethode, mit der Sie prüfen können, die verbundenen Eingabegeräte Gamecontroller sind. In diesem Fall ruft die Methode Geräte-IDs für die Controller Anschließend können Sie die einzelnen Geräte Identifiziere einen Spieler in deinem Spiel und verarbeite Spielaktionen für jeden verbundenen -Player separat ansehen. Weitere Informationen zur Unterstützung mehrerer Controller die gleichzeitig mit demselben Android-Gerät verbunden sind, Unterstützung mehrerer Controller

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;
}

Außerdem sollten Sie die einzelnen Eingabefähigkeiten überprüfen, die von einem verbundenen Controller unterstützt werden. Das kann beispielsweise nützlich sein, soll für dein Spiel nur die Eingabe über die physischen Steuerelemente genutzt werden, versteht.

Um zu ermitteln, ob ein bestimmter Schlüsselcode oder Achsencode von einem verbundenen Controllern verwenden:

  • Ab Android 4.4 (API-Level 19) kannst du feststellen, ob ein Schlüsselcode kann auf einem verbundenen Controller durch folgenden Aufruf hasKeys(int...)
  • Ab Android 3.1 (API-Level 12) finden Sie alle verfügbaren Achsen wird auf einem verbundenen Controller unterstützt, indem du zuerst getMotionRanges() Dann können Sie jeweils InputDevice.MotionRange-Objekt zurückgegeben, Aufruf getAxis(), um seine Achsen-ID abzurufen.

Tastendrücke des Gamepads verarbeiten

Abbildung 1 zeigt, wie Android Schlüsselcodes und Achsenwerte dem physischen Gerät zuordnet. die meisten Controller.

Abbildung 1: Profil für einen generischen Controller.

Die Callouts in der Abbildung beziehen sich auf Folgendes:

Gängige Tastencodes, die beim Drücken von Gamepad-Tasten generiert werden, sind BUTTON_A, BUTTON_B, BUTTON_SELECT, und BUTTON_START. Etwas Spiel Controller lösen auch den Tastencode DPAD_CENTER aus, wenn die Mitte des Steuerkreuzes gedrückt wird. Ihr Das Spiel kann den Schlüsselcode prüfen, indem es getKeyCode() aufruft oder über Rückrufe von Schlüsselereignissen wie onKeyDown(), Wenn es sich um ein Ereignis handelt, das für Ihr Spiel relevant ist, ins Spiel. In Tabelle 1 sind die empfohlenen Spielaktionen für die häufigsten Gamepad-Tasten.

Tabelle 1 Empfohlene Spielaktionen für Gamepads Schaltflächen.

Actionspiele Tastencode
Starte das Spiel im Hauptmenü oder pausiere das Spiel oder setze die Pausierung während des Spiels fort BUTTON_START*
Menü einblenden BUTTON_SELECT* und KEYCODE_MENU*
Entspricht dem Navigationsverhalten Zurück von Android, das in den Navigationsdesign . KEYCODE_BACK
Zurück zu einem vorherigen Menüelement BUTTON_B
Auswahl bestätigen oder primäre Spielaktion durchführen BUTTON_A und DPAD_CENTER

* Für dein Spiel sollte nicht die Schaltfläche „Start“, „Auswahl“ oder „Menü“ erforderlich sein Schaltflächen.

Tipp : Sie können auch einen Konfigurationsbildschirm bereitstellen. in Ihrem Spiel, damit Nutzer ihre eigenen Controller-Zuordnungen für Spieleaktionen.

Das folgende Snippet zeigt, wie Sie onKeyDown() bis die BUTTON_A und Drücken der DPAD_CENTER-Taste mit einer Spielaktion.

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;
    }
}

Hinweis: Unter Android 4.2 (API) Ebene 17) und niedriger ist, behandelt das System BUTTON_A als Android Standardmäßig die Taste Zurück. Wenn deine App diese Android- Versionen, achten Sie darauf, BUTTON_A als Hauptspiel Aktion ausführen. Um das aktuelle Android SDK zu ermitteln Version auf dem Gerät finden Sie in der Build.VERSION.SDK_INT-Wert.

Eingabe über die Richtungstasten

Das Steuerkreuz ist eine gängige physische Steuerung in vielen Spielen. Controller. Android zeigt, dass die Taste „Nach oben“ und „Nach unten“ des Steuerkreuzes so gedrückt wird: AXIS_HAT_Y Ereignisse mit einem Bereich von -1,0 (aufwärts) bis 1,0 (nach unten) und das Steuerkreuz LINKS oder RECHTS drücken als AXIS_HAT_X-Ereignisse mit einem Bereich von -1,0 (links) bis 1,0 (rechts) zu ändern.

Einige Controller melden das Drücken des Steuerkreuzes stattdessen mit einem Tastencode. Wenn Ihr Spiel das Drücken des Steuerkreuzes wichtig ist, solltest du die Ereignisse mit der Hutachse und das Steuerkreuz dieselben Eingabeereignisse verwenden, wie in Tabelle 2 empfohlen.

Tabelle 2: Empfohlene Standardaktionen für Spiele für die Steuerkreuztaste und Hut-Achsenwerte.

Actionspiele Tastencode des Steuerkreuzes Hat-Achsencode
Nach oben KEYCODE_DPAD_UP AXIS_HAT_Y (für die Werte 0 bis -1,0)
Nach unten KEYCODE_DPAD_DOWN AXIS_HAT_Y (für die Werte 0 bis 1,0)
Nach links bewegen KEYCODE_DPAD_LEFT AXIS_HAT_X (für die Werte 0 bis -1,0)
Nach rechts bewegen KEYCODE_DPAD_RIGHT AXIS_HAT_X (für die Werte 0 bis 1,0)

Das folgende Code-Snippet zeigt eine Hilfsklasse, mit der Sie und die Schlüsselcodewerte eines Eingabeereignisses, um die Richtung des Steuerkreuzes festzulegen.

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;
         }
     }
}

Du kannst diese Hilfsklasse überall dort in deinem Spiel verwenden, wo du sie verarbeiten möchtest. Eingabe über das Steuerkreuz (z. B. im onGenericMotionEvent() oder onKeyDown() Callbacks angezeigt.

Beispiel:

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.
    ...
}

Joystickbewegungen verarbeiten

Wenn Spieler einen Joystick auf ihren Controllern bewegen, meldet Android MotionEvent, die den ACTION_MOVE-Aktionscode und die aktualisierte Positionen der Joystickachsen. Ihr Spiel kann die Daten nutzen, die von die MotionEvent, um festzustellen, ob der Joystick bewegt wird, was wichtig ist.

Beachten Sie, dass Joystick-Bewegungsereignisse mehrere Bewegungsbeispiele in einem Batch zusammenfassen können. innerhalb eines einzelnen Objekts. Das MotionEvent-Objekt enthält die aktuelle Position jeder Joystickachse sowie mehrere historische für jede Achse anpassen. Beim Melden von Bewegungsereignissen mit dem Aktionscode ACTION_MOVE (wie Joystickbewegungen) fasst Android die Achsenwerte für Effizienz. Die historischen Werte für eine Achse bestehen aus den Satz verschiedener Werte, die älter als der aktuelle Achsenwert sind und aktueller als Werte, die bei früheren Bewegungsereignissen erfasst wurden. Weitere Informationen finden Sie in der MotionEvent.

Anhand der Verlaufsdaten kannst du ein Spiel genauer rendern Bewegung des Objekts basierend auf der Joystick-Eingabe. Bis die aktuellen und historischen Werte abzurufen, getAxisValue() oder getHistoricalAxisValue(). Sie können auch die Anzahl der bisherigen im Joystick-Ereignis einfügen, indem Sie getHistorySize()

Das folgende Snippet zeigt, wie Sie das Attribut onGenericMotionEvent()-Callback, um die Joystick-Eingabe zu verarbeiten. Zuerst sollten Sie historische Werte für eine Achse verarbeiten und dann ihre aktuelle Position verarbeiten.

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);
    }
}

Bevor Sie die Joystick-Eingabe verwenden können, müssen Sie überprüfen, ob der Joystick und dann die Bewegung der Achsen entsprechend berechnen. Joysticks haben eine flache Fläche, d. h. einen Wertebereich in der Nähe der Koordinate (0,0) an dem die Achse als zentriert angesehen wird. Wenn der Achsenwert Android liegt im flachen Bereich, du solltest den Controller so behandeln, (d. h. entlang beider Achsen bewegungslos).

Das folgende Snippet zeigt eine Hilfsmethode, mit der die Bewegung entlang für jede Achse. Sie rufen diesen Helper in der Methode processJoystickInput() auf wie unten beschrieben.

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;
}

Zusammenfassend lässt sich sagen, wie Sie Joystickbewegungen Ihr Spiel:

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
}

Zur Unterstützung von Controllern mit komplexeren Joystick-Funktionen zu maximieren, befolgen Sie diese Best Practices:

  • Du kannst Sticks mit zwei Controllern bedienen. Viele Controller haben mit dem linken und rechten Joystick. Für den linken Stick: Android meldet horizontale Bewegungen als AXIS_X-Ereignisse und vertikale Bewegungen als AXIS_Y-Ereignisse. Für den rechten Stick erfasst Android horizontale Bewegungen als AXIS_Z Ereignisse und vertikale Bewegungen als AXIS_RZ Ereignisse. Achten Sie darauf, bleiben beide Controller im Code.
  • Drücken der Schulterauslöser handhaben (aber alternative Eingabe anbieten) Methoden). Einige Controller haben die linke und rechte Schulter Trigger. Wenn diese Auslöser vorhanden sind, meldet Android, dass der Auslöser links gedrückt wird. als AXIS_LTRIGGER-Ereignis und als rechten Trigger drücken Ereignis vom Typ AXIS_RTRIGGER. Auf Android-Geräten 4.3 (API-Level 18), ein Controller, der einen AXIS_LTRIGGER meldet außerdem: identischer Wert für die AXIS_BRAKE-Achse. Die Dasselbe gilt für AXIS_RTRIGGER und AXIS_GAS. Android meldet alle analogen Trigger drückt einen normalisierten Wert von 0.0 (freigegeben) bis 1.0 (vollständig gedrückt). Nicht Alle Controller haben Trigger. Erwäge daher, den Spielern zu erlauben, diese auszuführen. mit anderen Schaltflächen spielen.