Obsługa kilku kontrolerów do gier

Większość gier została zaprojektowana z myślą o jednym użytkowniku każdego urządzenia z Androidem, Można również obsługiwać wielu użytkowników za pomocą kontrolerów do gier, jednocześnie na tym samym urządzeniu z Androidem.

W tym wykładzie omówione zostaną podstawowe techniki radzenia sobie z danymi gra wieloosobowa na różnych urządzeniach, korzystając z kilku połączonych kontrolerów. Obejmuje to m.in. zachowanie mapowania między awatarami graczy a każdym urządzeniem kontrolera; odpowiednie zdarzenia wejściowe kontrolera przetwarzania.

Zmapuj odtwarzacze na identyfikatory urządzeń kontrolera

Gdy kontroler gry jest podłączony do urządzenia z Androidem, przypisuje mu identyfikator urządzenia w postaci liczby całkowitej. Możesz uzyskać identyfikatory połączonych urządzeń kontrolerów gier, wywołując metodę InputDevice.getDeviceIds(), jak pokazano w sekcji Sprawdzanie, czy kontroler do gier jest połączony. Następnie możesz powiązać każdy z nich, z graczem w grze i przetwarzaj działania każdego z nich z osobna.

Uwaga: na urządzeniach z Androidem 4.1 (interfejs API) poziomu 16) i wyższych, deskryptor urządzenia wejściowego można uzyskać za pomocą funkcji getDescriptor(), która zwraca unikalną wartość wartość ciągu trwałego dla urządzenia wejściowego. W przeciwieństwie do identyfikatora urządzenia deskryptor nie zmienia się nawet wtedy, gdy urządzenie wejściowe jest odłączone, podłączone ponownie, ponowna konfiguracja.

Fragment kodu poniżej pokazuje, jak używać tabeli SparseArray aby powiązać awatar gracza z konkretnym kontrolerem. W tym przykładzie para klucz-wartość Zmienna mShips przechowuje kolekcję Ship obiektów. Nowy awatar gracza jest tworzony w grze, gdy użytkownik podłącza nowy kontroler. i usuwane po usunięciu powiązanego kontrolera.

Wywołanie zwrotne onInputDeviceAdded() i onInputDeviceRemoved() są częścią warstwy abstrakcji wprowadzonej Obsługa kontrolerów na różnych wersjach Androida. Dzięki wdrożeniu na wywołaniach zwrotnych detektora, gra może identyfikować identyfikator urządzenia kontrolera gry, gdy dodanie lub usunięcie kontrolera. Wykrywanie jest zgodne z Androidem 2.3 (poziom interfejsu API 9) i wyższy.

Kotlin

private val ships = SparseArray<Ship>()

override fun onInputDeviceAdded(deviceId: Int) {
    getShipForID(deviceId)
}

override fun onInputDeviceRemoved(deviceId: Int) {
    removeShipForID(deviceId)
}

private fun getShipForID(shipID: Int): Ship {
    return ships.get(shipID) ?: Ship().also {
        ships.append(shipID, it)
    }
}

private fun removeShipForID(shipID: Int) {
    ships.remove(shipID)
}

Java

private final SparseArray<Ship> ships = new SparseArray<Ship>();

@Override
public void onInputDeviceAdded(int deviceId) {
    getShipForID(deviceId);
}

@Override
public void onInputDeviceRemoved(int deviceId) {
    removeShipForID(deviceId);
}

private Ship getShipForID(int shipID) {
    Ship currentShip = ships.get(shipID);
    if ( null == currentShip ) {
        currentShip = new Ship();
        ships.append(shipID, currentShip);
    }
    return currentShip;
}

private void removeShipForID(int shipID) {
    ships.remove(shipID);
}

Przetwarzaj dane wejściowe kontrolera

Twoja gra powinna wykonywać tę pętlę, aby przetworzyć danych wejściowych z kilku kontrolerów:

  1. Wykrywanie, czy wystąpiło zdarzenie wejściowe.
  2. Identyfikowanie źródła danych wejściowych i jego identyfikatora urządzenia.
  3. W zależności od działania wskazanego przez kod klucza zdarzenia wejściowego lub wartość osi zaktualizować awatara gracza powiązany z identyfikatorem urządzenia.
  4. Renderowanie i aktualizowanie interfejsu użytkownika.

Dane wejściowe: KeyEvent i MotionEvent zdarzenia mają powiązane identyfikatory urządzeń. Twoja gra może wykorzystać: aby określić, z którego kontrolera pochodzi zdarzenie wejściowe, i zaktualizować awatar gracza powiązanego z tym kontrolerem.

Ten fragment kodu pokazuje, jak uzyskać odniesienie do awatara gracza odpowiadający identyfikatorowi kontrolera do gier i zaktualizować grę na podstawie naciśnięcie przycisku użytkownika na tym kontrolerze.

Kotlin

override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
    if (event.source and InputDevice.SOURCE_GAMEPAD == InputDevice.SOURCE_GAMEPAD) {
        event.deviceId.takeIf { it != -1 }?.also { deviceId ->
            val currentShip: Ship = getShipForID(deviceId)
            // Based on which key was pressed, update the player avatar
            // (e.g. set the ship headings or fire lasers)
            return true
        }
    }
    return super.onKeyDown(keyCode, event)
}

Java

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if ((event.getSource() & InputDevice.SOURCE_GAMEPAD)
                == InputDevice.SOURCE_GAMEPAD) {
        int deviceId = event.getDeviceId();
        if (deviceId != -1) {
            Ship currentShip = getShipForId(deviceId);
            // Based on which key was pressed, update the player avatar
            // (e.g. set the ship headings or fire lasers)
            ...
            return true;
        }
    }
    return super.onKeyDown(keyCode, event);
}

Uwaga: zgodnie ze sprawdzonymi metodami, kontroler do gier rozłącza się. Wstrzymaj grę i zapytaj użytkownika, Użytkownik chce ponownie nawiązać połączenie.