Birden fazla oyun kumandasını destekleme

Çoğu oyun, Android destekli cihazlarda tek kullanıcıyı destekleyecek şekilde tasarlanmış olsa da aynı Android destekli cihaza aynı anda bağlanan oyun kumandalarıyla birden fazla kullanıcıyı desteklemek de mümkündür.

Bu derste, tek cihazda çok oyunculu oyununuzda birden fazla bağlı kumandadan gelen girişleri işleme ile ilgili bazı temel teknikler ele alınmaktadır. Buna, oyuncu avatarları ile her bir kontrol cihazı arasında eşleme yapılması ve kontrol cihazı giriş etkinliklerinin uygun şekilde işlenmesi dahildir.

Oyuncuları kontrol cihazı kimlikleriyle eşleme

Bir oyun kumandası Android destekli bir cihaza bağlandığında sistem, kumandaya tam sayı bir cihaz kimliği atar. Bağlı oyun kumandalarının cihaz kimliklerini, InputDevice.getDeviceIds() işlevini çağırarak alabilirsiniz. Bu işlevin kullanımı Oyun Kumandasının Bağlı Olduğunu Doğrulama bölümünde gösterilmiştir. Daha sonra her cihaz kimliğini oyununuzdaki bir oyuncuyla ilişkilendirebilir ve her oyuncu için oyun işlemlerini ayrı ayrı işleyebilirsiniz.

Kod snippet'inde, bir oyuncunun avatarını belirli bir kumandayla ilişkilendirmek için SparseArray nasıl kullanılacağı gösterilmektedir. Bu örnekte, mShips değişkeni bir Ship nesne koleksiyonunu saklar. Kullanıcı yeni bir kumanda bağladığında oyun içinde yeni bir oyuncu avatarı oluşturulur. İlişkili kumanda çıkarıldığında ise bu avatar kaldırılır.

onInputDeviceAdded() ve onInputDeviceRemoved() geri çağırma yöntemleri, Farklı Android Sürümlerinde Denetleyicileri Destekleme bölümünde tanıtılan soyutlama katmanının bir parçasıdır. Bu dinleyici geri çağırmalarını uygulayarak oyununuz, bir kontrol cihazı eklendiğinde veya kaldırıldığında oyun kontrol cihazının cihaz kimliğini tanımlayabilir. Bu algılama, Android 2.3 (API seviyesi 9) ve sonraki sürümlerle uyumludur.

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

Birden fazla kumanda girişini işleme

Oyununuzun, birden fazla kontrol cihazından gelen girişleri işlemek için aşağıdaki döngüyü yürütmesi gerekir:

  1. Bir giriş etkinliğinin gerçekleşip gerçekleşmediğini algılar.
  2. Giriş kaynağını ve cihaz kimliğini belirleyin.
  3. Giriş etkinliği anahtar kodu veya eksen değeriyle belirtilen işleme göre, bu cihaz kimliğiyle ilişkili oyuncu avatarını güncelleyin.
  4. Kullanıcı arayüzünü oluşturma ve güncelleme

KeyEvent ve MotionEvent giriş etkinlikleriyle ilişkilendirilmiş cihaz kimlikleri vardır. Oyununuz, giriş etkinliğinin hangi kumandadan geldiğini belirlemek ve bu kumandayla ilişkili oyuncu avatarını güncellemek için bu bilgiden yararlanabilir.

Aşağıdaki kod snippet'i, bir oyun kumandası cihaz kimliğine karşılık gelen bir oyuncu avatarı referansını nasıl alabileceğinizi ve oyunu, kullanıcının bu kumandadaki düğmeye basmasına göre nasıl güncelleyebileceğinizi gösterir.

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