एक से ज़्यादा गेम कंट्रोलर के साथ काम करें

ज़्यादातर गेम, Android पर चलने वाले डिवाइस पर एक ही उपयोगकर्ता के लिए डिज़ाइन किए जाते हैं. हालांकि, Android पर चलने वाले एक ही डिवाइस पर एक साथ कनेक्ट किए गए गेम कंट्रोलर की मदद से, एक से ज़्यादा उपयोगकर्ताओं के लिए गेम खेले जा सकते हैं.

इस सबक में, एक ही डिवाइस पर खेले जाने वाले मल्टीप्लेयर गेम में, कनेक्ट किए गए एक से ज़्यादा कंट्रोलर से इनपुट मैनेज करने की कुछ बुनियादी तकनीकों के बारे में बताया गया है. इसमें, खिलाड़ियों के अवतारों और हर कंट्रोलर डिवाइस के बीच मैपिंग बनाए रखना और कंट्रोलर के इनपुट इवेंट को सही तरीके से प्रोसेस करना शामिल है.

खिलाड़ियों को कंट्रोलर डिवाइस आईडी से मैप करना

जब कोई गेम कंट्रोलर, Android पर चलने वाले किसी डिवाइस से कनेक्ट होता है, तो सिस्टम उसे एक इंटिजर डिवाइस आईडी असाइन करता है. कनेक्ट किए गए गेम कंट्रोलर के डिवाइस आईडी पाने के लिए, InputDevice.getDeviceIds() को कॉल किया जा सकता है. जैसा कि गेम कंट्रोलर के कनेक्ट होने की पुष्टि करना में दिखाया गया है. इसके बाद, हर डिवाइस आईडी को अपने गेम में किसी खिलाड़ी से जोड़ा जा सकता है. साथ ही, हर खिलाड़ी के लिए गेम की कार्रवाइयों को अलग-अलग प्रोसेस किया जा सकता है.

कोड स्निपेट में दिखाया गया है कि किसी खिलाड़ी के अवतार को किसी खास कंट्रोलर से जोड़ने के लिए, SparseArray का इस्तेमाल कैसे किया जाता है. इस उदाहरण में, mShips वैरिएबल में Ship ऑब्जेक्ट का कलेक्शन सेव होता है. जब कोई उपयोगकर्ता नया कंट्रोलर जोड़ता है, तो गेम में एक नया प्लेयर अवतार बनता है. साथ ही, जब उससे जुड़ा कंट्रोलर हटाया जाता है, तो वह अवतार भी हट जाता है.

onInputDeviceAdded() और onInputDeviceRemoved() कॉलबैक के तरीके Android के अलग-अलग वर्शन पर कंट्रोलर की सुविधा उपलब्ध कराने के लिए, ऐब्स्ट्रैक्शन लेयर का हिस्सा हैं. इन लिसनर कॉलबैक को लागू करके, आपका गेम कंट्रोलर जोड़ने या हटाने पर, गेम कंट्रोलर के डिवाइस आईडी की पहचान कर सकता है. यह सुविधा, Android 2.3 (एपीआई लेवल 9) और इसके बाद के वर्शन पर काम करती है.

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

एक से ज़्यादा कंट्रोलर के इनपुट को प्रोसेस करना

एक से ज़्यादा कंट्रोलर से इनपुट प्रोसेस करने के लिए, आपके गेम को यह लूप चलाना चाहिए:

  1. पता लगाएं कि कोई इनपुट इवेंट हुआ है या नहीं.
  2. इनपुट के सोर्स और उसके डिवाइस आईडी की पहचान करें.
  3. इनपुट इवेंट के की कोड या ऐक्सिस वैल्यू से पता चलने वाली कार्रवाई के आधार पर, उस डिवाइस आईडी से जुड़े प्लेयर अवतार को अपडेट करें.
  4. यूज़र इंटरफ़ेस को रेंडर और अपडेट करें.

KeyEvent और MotionEvent इनपुट इवेंट से डिवाइस आईडी जुड़े होते हैं. आपका गेम इसका फ़ायदा उठाकर यह पता लगा सकता है कि इनपुट इवेंट किस कंट्रोलर से आया है. साथ ही, उस कंट्रोलर से जुड़े प्लेयर अवतार को अपडेट किया जा सकता है.

यहां दिए गए कोड स्निपेट में दिखाया गया है कि गेम कंट्रोलर के डिवाइस आईडी के हिसाब से, प्लेयर अवतार का रेफ़रंस कैसे पाया जा सकता है. साथ ही, उस कंट्रोलर पर उपयोगकर्ता के बटन दबाने के आधार पर, गेम को कैसे अपडेट किया जा सकता है.

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