Mendukung beberapa pengontrol game

Meskipun sebagian besar game didesain untuk mendukung satu pengguna per perangkat Android, Anda juga dapat mendukung beberapa pengguna dengan pengontrol {i>game<i} yang terhubung secara bersamaan di perangkat Android yang sama.

Tutorial ini mencakup beberapa teknik dasar untuk menangani input dalam single game multiplayer perangkat dari beberapa pengontrol yang terhubung. Hal ini mencakup mempertahankan pemetaan antara avatar pemain dan setiap perangkat pengontrol, dan memproses peristiwa input pengontrol dengan tepat.

Memetakan pemain ke ID perangkat pengontrol

Saat pengontrol game terhubung ke perangkat Android, sistem menetapkan ID perangkat bilangan bulat. Anda bisa mendapatkan ID perangkat untuk pengontrol game dengan memanggil InputDevice.getDeviceIds(), seperti yang ditunjukkan dalam Memverifikasi Pengontrol Game Tersambung. Anda kemudian dapat menghubungkan setiap ID perangkat dengan pemain di game Anda, dan proses tindakan game untuk setiap pemain secara terpisah.

Catatan: Pada perangkat yang menjalankan Android 4.1 (API level 16) dan yang lebih tinggi, Anda bisa mendapatkan deskriptor perangkat input menggunakan getDescriptor(), yang menampilkan untuk perangkat input. Tidak seperti ID perangkat, deskriptor nilai tidak akan berubah bahkan jika perangkat {i>input <i} putus, terhubung kembali, atau dikonfigurasi ulang.

Cuplikan kode di bawah menunjukkan cara menggunakan SparseArray untuk mengaitkan avatar pemain dengan pengontrol tertentu. Dalam contoh ini, Variabel mShips menyimpan kumpulan objek Ship. Fitur baru avatar pemain dibuat dalam game saat {i> controller<i} baru dipasang oleh pengguna, dan dihapus saat pengontrol terkaitnya dihapus.

Callback onInputDeviceAdded() dan onInputDeviceRemoved() adalah bagian dari lapisan abstraksi yang diperkenalkan di Mendukung Pengontrol di Berbagai Versi Android. Dengan menerapkan Anda, game Anda dapat mengidentifikasi ID perangkat pengontrol game saat {i>controller<i} ditambahkan atau dihapus. Deteksi ini kompatibel dengan Android 2.3 (level API 9) dan yang lebih tinggi.

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

Memproses beberapa input pengontrol

Game Anda harus menjalankan loop berikut untuk memproses input dari beberapa pengontrol:

  1. Mendeteksi apakah peristiwa input terjadi.
  2. Mengidentifikasi sumber input dan ID perangkatnya.
  3. Berdasarkan tindakan yang ditunjukkan oleh kode tombol peristiwa input atau nilai sumbu, perbarui avatar pemain yang terkait dengan ID perangkat tersebut.
  4. Merender dan memperbarui antarmuka pengguna.

Input KeyEvent dan MotionEvent peristiwa memiliki ID perangkat yang terkait dengannya. Game Anda dapat memanfaatkan ini untuk menentukan dari pengontrol mana peristiwa input itu berasal, dan memperbarui avatar pemain yang terkait dengan pengontrol tersebut.

Cuplikan kode berikut menunjukkan cara mendapatkan referensi avatar pemain sesuai dengan ID perangkat pengontrol game, dan memperbarui game berdasarkan pengguna menekan tombol {i>controller<i} tersebut.

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

Catatan: Sebagai praktik terbaik, saat perilaku pengguna pengontrol game terputus, Anda harus menjeda game dan bertanya apakah pengguna ingin terhubung kembali.