Birden fazla oyun kumandasını destekleme

Çoğu oyun her Android cihazda tek bir kullanıcıyı destekleyecek şekilde tasarlanmış olsa da Aynı zamanda oyun kumandalarıyla birden fazla kullanıcıyı desteklemek de aynı Android cihazda aynı anda bağlanıyor.

Bu ders, single'ınızda girdi yönetimiyle ilgili bazı temel teknikleri cihaza bağlı birden fazla kumandadan alınan çok oyunculu oyun oynamanıza olanak tanır. Buna şunlar dâhildir: oyuncu avatarları ile her kumanda cihazı arasında bir eşleme sağlar ve denetleyici giriş etkinliklerini uygun şekilde işleme.

Oyuncuları kumanda cihaz kimlikleriyle eşleme

Oyun kumandası bir Android cihaza bağlandığında sistem, bir tamsayı cihaz kimliği atar. Bağlı cihazlar için cihaz kimliklerini Verify a Game Controller'ın (Oyun Kumandası Bağlı Olduğunu Doğrulama) bölümünde gösterildiği gibi, InputDevice.getDeviceIds() çağırarak oyun kumandaları talep edebilirsiniz. Daha sonra her bir cihaz kimliğini kontrol edin ve her oyuncu için oyun işlemlerini ayrı ayrı işleyin.

Not: Android 4.1 (API) çalıştıran cihazlarda düzeyi 16) ve sonraki sürümleri kullanıyorsanız giriş cihazının tanımlayıcısını getDescriptor(), benzersiz bir değer döndürür. giriş cihazı için kalıcı dize değeri. Tanımlayıcı, cihaz kimliğinin aksine değeri, giriş cihazı bağlı olsa, yeniden bağlanılsa veya yeniden yapılandırıldı.

Aşağıdaki kod snippet'i, SparseArray özelliğinin nasıl kullanılacağını göstermektedir kullanabilirsiniz. Bu örnekte mShips değişkeni, Ship nesneden oluşan bir koleksiyon depolar. Yeni bir Kullanıcı tarafından yeni bir kumanda takıldığında oyuncu avatarı oluşturulur. ve ilişkili kumandası kaldırıldığında kaldırılır.

onInputDeviceAdded() ve onInputDeviceRemoved() geri çağırması yöntemleri, Tüm Android Sürümlerinde Kumandaları Destekleme. Bu özellikleri uygulayarak dinleyici geri çağırması sonucunda, bir oyun kumandasının cihaz kimliğini denetleyici eklendiğinde veya kaldırıldığında. Bu algılama özelliği Android 2.3 ile uyumludur. (API düzeyi 9) ve daha yeni sürümler.

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şle

Oyununuz, işleme almak için aşağıdaki döngüyü yürütmelidir: birden çok denetleyiciden giriş:

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

KeyEvent ve MotionEvent girişi etkinliklerin cihaz kimlikleri ilişkilendirilmiş. Oyununuz, bunu, giriş etkinliğinin hangi denetleyiciden geldiğini belirler ve oyuncu avatarı olmalıdır.

Aşağıdaki kod snippet'i, oyuncu avatarı referansını nasıl alabileceğinizi gösterir. olduğunu ve oyunu kullanıcı düğmesine bastığını unutmayın.

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

Not: En iyi uygulama olarak, bir kullanıcının bağlantısı kesiliyorsa oyunu duraklatmalı ve kullanıcıya yeniden bağlantı kurmak istiyor.