Obsługuj działania kontrolera

Na poziomie systemu Android zgłasza kody zdarzeń wejściowych z kontrolerów gier jako kody kluczy i wartości osi Androida. W grze możesz otrzymać te kody i przekształcać je w konkretne działania w grze.

Gdy gracze łączą się fizycznie lub bezprzewodowo z kontrolerem do gier urządzeń z Androidem, system automatycznie wykryje kontroler, jako urządzenie wejściowe i rozpoczyna raportowanie zdarzeń wejściowych. Twoja gra może otrzymywać tych zdarzeń wejściowych, implementując poniższe metody wywołania zwrotnego w aktywnych Activity lub zaznaczone View (należy zaimplementuj wywołania zwrotne dla Activity albo View, ale nie oba):

Zalecanym sposobem jest rejestrowanie zdarzeń z konkretny obiekt View, z którym użytkownik wchodzi w interakcję. Aby uzyskać informacje, sprawdź następujące obiekty podane przez wywołania zwrotne o typie otrzymanego zdarzenia wejściowego:

KeyEvent
Obiekt opisujący zdarzeń przycisków pada kierunkowego i pada do gier. Kluczowym zdarzeniom towarzyszy reklama kod klucza wskazujący wywołany konkretny przycisk, np. DPAD_DOWN lub BUTTON_A. Możesz uzyskać kod klucza, wywołując getKeyCode() lub z klucza wywołań zwrotnych zdarzeń, takich jak onKeyDown()
MotionEvent
Obiekt opisujący dane wejściowe pochodzące z joysticka i spustu pobocznego i ruchu. Zdarzeniom ruchu towarzyszy kod działania i zestaw wartości osi. Kod działania określa zachodzącą zmianę stanu np. poruszając joystickiem. Wartości na osi opisują pozycję i inne parametry właściwości ruchu dla określonej kontroli fizycznej, takich jak AXIS_X lub AXIS_RTRIGGER Aby uzyskać kod działania, wywołując funkcję getAction() i wartość osi przez Dzwonię pod numer getAxisValue().

Z tego wykładu dowiesz się, jak radzić sobie z danymi pochodzącymi z najczęstszych typów elementy sterujące (przyciski pada do gier, pady kierunkowe i joysticki) na ekranie gry przez wdrożenie View metoda wywołania zwrotnego i przetwarzanie KeyEvent i MotionEvent obiektów.

Sprawdź, czy kontroler do gier jest podłączony

Podczas raportowania zdarzeń wejściowych Android nie rozróżnia między zdarzeniami pochodzącymi z kontrolera innego niż kontroler do gry a zdarzeniami, za pomocą kontrolera do gier. Na przykład działanie na ekranie dotykowym generuje Zdarzenie AXIS_X, które reprezentuje symbol X współrzędną powierzchni dotykowej, ale joystick generuje Zdarzenie AXIS_X, które reprezentuje pozycję X joysticka. Jeśli w przypadku gry zależy od obsługi danych wejściowych kontrolera, najpierw sprawdź, że zdarzenie wejściowe pochodzi z odpowiedniego typu źródła.

Aby sprawdzić, czy podłączone urządzenie wejściowe jest kontrolerem gry, wywołaj getSources(), aby uzyskać połączone pole bitowe typów źródeł wejściowych obsługiwanych przez dane urządzenie. Następnie można sprawdzić, czy ustaw te pola:

  • Typ źródła SOURCE_GAMEPAD wskazuje czy urządzenie wejściowe ma przyciski pada do gier (np. BUTTON_A). Pamiętaj, że to źródło nie wskazuje bezpośrednio, czy kontroler do gier ma przyciski padów kierunkowych, chociaż większość padów do gier ma sterowanie kierunkowe.
  • Typ źródła SOURCE_DPAD wskazuje, że urządzenie wejściowe ma przyciski pada kierunkowego (np. DPAD_UP).
  • Typ źródła: SOURCE_JOYSTICK wskazuje, że urządzenie wejściowe jest wyposażone w analogowe gałki sterujące (np. joystick rejestrujący ruchy wzdłuż linii AXIS_X i AXIS_Y).

Poniższy fragment kodu zawiera metodę pomocniczą, która pozwala sprawdzić, czy podłączone urządzenia wejściowe to kontrolery gier. Jeśli tak, metoda pobiera identyfikatory urządzeń kontrolerów do gier. Następnie możesz powiązać każde urządzenie Identyfikator gracza w grze i przetwarzaj działania w przypadku każdego połączenia z osobna. Dowiedz się więcej o obsłudze kilku kontrolerów do gier które są jednocześnie połączone z tym samym urządzeniem z Androidem, zobacz Obsługa wielu kontrolerów do gier.

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

Warto też sprawdzić możliwości indywidualnego wprowadzania tekstu obsługiwane przez podłączony kontroler do gier. Może to być przydatne, jeśli na przykład chcesz, aby gra korzystała tylko z danych wejściowych z zestawu elementów sterujących; .

Do wykrywania, czy określony kod klucza lub osi jest obsługiwany przez połączone kontroler do gier, użyj tych technik:

  • W Androidzie 4.4 (poziom interfejsu API 19) lub nowszym możesz sprawdzić, czy kod klucza obsługiwane na połączonym kontrolerze do gier przez wywołanie hasKeys(int...)
  • W Androidzie 3.1 (poziom interfejsu API 12) lub nowszym znajdziesz wszystkie dostępne osie obsługiwane na połączonym kontrolerze do gier po pierwszym wywołaniu getMotionRanges() Następnie w każdym kolejnym kroku Zwrócono InputDevice.MotionRange obiekt, wywołanie getAxis(), aby uzyskać identyfikator jej osi.

Przetwarzaj naciśnięcia przycisków na padzie do gier

Rysunek 1 pokazuje, jak Android mapuje kody kluczy i wartości osi na większości kontrolerów do gier.

Rysunek 1. Profil podstawowego kontrolera do gier.

Objaśnienia na ilustracji odnoszą się do tych informacji:

Typowe kody klawiszy generowane przez naciśnięcia przycisków na padzie do gier to BUTTON_A, BUTTON_B, BUTTON_SELECT, i BUTTON_START. Jakaś gra kontrolery uruchamiają też kod klawisza DPAD_CENTER po naciśnięciu środkowej części paska poprzeczki na padzie kierunkowym. Twoje gra może sprawdzić kod klucza, wywołując funkcję getKeyCode() lub wywołań zwrotnych kluczowych zdarzeń, takich jak onKeyDown(), Jeśli jest to zdarzenie związane z grą, potraktuj je jako akcji. Tabela 1 zawiera listę zalecanych działań w grach do przyciski pada do gier.

Tabela 1. Zalecane działania w grze na pada do gier przyciskami.

Akcja Kod klawisza przycisku
Uruchom grę w menu głównym albo wstrzymaj/wznów grę podczas gry BUTTON_START*
Wyświetl menu BUTTON_SELECT* i KEYCODE_MENU*
Takie same jak w przypadku nawigacji Wstecz w Androidzie opisane w Projekt nawigacji Google. KEYCODE_BACK
Powrót do poprzedniego elementu w menu BUTTON_B
Potwierdź wybór lub wykonaj główne działanie w grze BUTTON_A i DPAD_CENTER

* Gra nie powinna polegać na obecności przycisków Start, Select ani Menu.

Wskazówka: rozważ dodanie ekranu konfiguracji pozwala użytkownikom personalizować własne mapowania kontrolera działań w grze.

Ten fragment kodu pokazuje, jak zastąpić onKeyDown() do kojarz BUTTON_A i Naciśnięcia przycisku: DPAD_CENTER z akcją w grze.

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

Uwaga: na Androidzie 4.2 (interfejs API) 17) i niższym, system traktuje BUTTON_A jako Androida domyślny klawisz Wstecz. Jeśli Twoja aplikacja obsługuje te Androida pamiętaj, aby traktować te wersje BUTTON_A jako główna gra działania. Aby określić bieżący pakiet Android SDK wersji na urządzeniu, zapoznaj się z Wartość: Build.VERSION.SDK_INT.

Przetwarzaj wprowadzanie za pomocą pada kierunkowego

Czterokierunkowy pad kierunkowy (pad kierunkowy) jest standardowym elementem wielu gier i kontrolerach. Android zgłasza naciśnięcia przycisków W GÓRĘ i W DÓŁ na padzie kierunkowym jako AXIS_HAT_Y zdarzeń z zakresem od -1,0 (góra) do 1,0 (dół), a pad kierunkowy w lewo lub w prawo naciska jako Zdarzenia (AXIS_HAT_X) o zakresie od -1,0 (od lewej) do 1,0 (po prawej).

Niektóre kontrolery zgłaszają naciśnięcia na padach kierunkowych wraz z kodem klawisza. Jeśli Twoja gra naciska na pad kierunkowy, należy traktować zdarzenia osi kapelusza oraz kody klawiszy jako te same zdarzenia wejściowe, zgodnie z zaleceniami w tabeli 2.

Tabela 2. Zalecane domyślne działania w grze dla klawiszy na padzie kierunkowym kodów i wartości osi kapeluszy.

Akcja Kod klawisza pada kierunkowego Kod osi kapelusza
W górę KEYCODE_DPAD_UP AXIS_HAT_Y (dla wartości od 0 do -1,0)
W dół KEYCODE_DPAD_DOWN AXIS_HAT_Y (dla wartości od 0 do 1,0)
Przenieś w lewo KEYCODE_DPAD_LEFT AXIS_HAT_X (dla wartości od 0 do -1,0)
Przenieś w prawo KEYCODE_DPAD_RIGHT AXIS_HAT_X (dla wartości od 0 do 1,0)

Ten fragment kodu pokazuje klasę pomocniczą, która pozwala sprawdzić kapelusz wartości osi i kodu klucza ze zdarzenia wejściowego w celu określenia kierunku pada kierunkowego.

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

Tej klasy pomocniczej możesz używać w grze, gdziekolwiek chcesz: Wprowadzanie tekstu na padzie kierunkowym (na przykład w onGenericMotionEvent() lub onKeyDown() wywołania zwrotne).

Na przykład:

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

Przetwarzaj ruchy joysticka

Gdy gracz porusza joystickiem na kontrolerach do gier, Android zgłasza MotionEvent, który zawiera parametr ACTION_MOVE – kod działania i zaktualizowane położenie osi joysticka. Twoja gra może używać danych dostarczonych przez MotionEvent, by sprawdzić, czy ruch joysticka na to, co się wydarzyło.

Pamiętaj, że zdarzenia ruchu joysticka mogą zgrupować wiele próbek ruchu. w obrębie jednego obiektu. Obiekt MotionEvent zawiera bieżącej pozycji dla każdej osi joysticka oraz wielu historycznych dla każdej osi. Podczas raportowania zdarzeń ruchu o kodzie działania ACTION_MOVE (np. ruchów joysticka), Android grupuje wartości osi dla wydajności. Wartości historyczne na osi składają się zbiór unikalnych wartości starszych niż bieżąca wartość osi i nowszych niż we wszystkich wcześniejszych zdarzeniach ruchu. Zobacz MotionEvent – więcej informacji.

Możesz wykorzystać informacje historyczne, aby dokładniej renderować grę ruchu obiektu w oparciu o dane wejściowe joysticka. Do dla pobierania wartości bieżących i historycznych, wywołanie getAxisValue() lub getHistoricalAxisValue(). Możesz też sprawdzić liczbę punktów w zdarzeniu joysticka, wywołując getHistorySize()

Ten fragment kodu pokazuje, jak możesz zastąpić Wywołanie zwrotne onGenericMotionEvent() do przetwarzania danych wejściowych joysticka. Najpierw musisz przetwarzania wartości historycznych osi, a następnie przetwarzania jej bieżącej pozycji.

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

Przed użyciem sterowania joystickiem należy sprawdzić, czy a następnie odpowiednio obliczyć ruchy osi. Zwykle joysticki mają płaski obszar, czyli zakres wartości w pobliżu współrzędnych (0,0) na której oś jest uznawana za wyśrodkowaną. Jeśli wartość osi raportowana przez Android to płaski obszar, a kontroler należy traktować tak, jak spoczynek (czyli ruch nie może się ruszać wzdłuż obu osi).

Ten fragment kodu przedstawia metodę pomocniczą, która oblicza ruch wzdłuż każdej osi. Wywołanie tej funkcji pomocniczej w metodzie processJoystickInput() opisane poniżej.

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

Oto jak można przetwarzać ruchy joysticka w Twoja gra:

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
}

na potrzeby obsługi bardziej zaawansowanych kontrolerów do gier; funkcji wykraczających poza pojedynczy joystick, zastosuj następujące sprawdzone metody:

  • Obsługuj 2 gałki kontrolera. Wiele kontrolerów do gier ma lewy i prawy joystick. Na lewym skrzydle: Android raportuje ruchy w poziomie jako AXIS_X zdarzeń a ruchy w pionie jako zdarzenia AXIS_Y. Ruch w poziomie prawej drążka jest raportowany jako AXIS_Z zdarzenia i zmiany w pionie jako Wydarzenia: AXIS_RZ. Upewnij się, że obsługa obydwa kontrolery pozostają w kodzie.
  • Obsługuj naciśnięcia spustu pobocznego (ale podaj inne dane wejściowe ). Niektóre kontrolery mają lewe i prawe barki wyzwalaczy. Jeśli te reguły są obecne, Android zgłasza naciśnięcie lewego spustu jako zdarzenie AXIS_LTRIGGER oraz Naciśnięcie prawego spustu AXIS_RTRIGGER. Android 4.3 (poziom interfejsu API 18) – kontroler, który tworzy AXIS_LTRIGGER zgłasza też jednakowa wartość na osi AXIS_BRAKE. to samo dotyczy AXIS_RTRIGGER i AXIS_GAS Android zgłasza wszystkie aktywatory analogowe dociśnień o znormalizowanej wartości od 0,0 (zwolnione) do 1,0 (w pełni naciśnięte). Nie Wszystkie kontrolery mają wyzwalacze, więc rozważ zezwolenie graczom na wykonywanie tych czynności działania w grze za pomocą innych przycisków.