कंट्रोलर से जुड़ी कार्रवाइयां मैनेज करना

सिस्टम के लेवल पर, Android, गेम कंट्रोलर से इवेंट कोड डालने की रिपोर्ट देता है को Android कुंजी कोड और ऐक्सिस की वैल्यू के तौर पर सेट कर सकते हैं. अपने गेम में, आपको ये कोड मिल सकते हैं और उन्हें खास इन-गेम ऐक्शन में बदल सकते हैं.

जब खिलाड़ी फ़िज़िकल तौर पर कनेक्ट करते हैं या वायरलेस तरीके से गेम कंट्रोलर को पेयर करते हैं जब सिस्टम, अपने-आप कंट्रोलर का पता लगाता है, तो और अपने इनपुट इवेंट की रिपोर्टिंग शुरू कर देता है. आपका गेम ये पा सकता है अपने ऐक्टिव सिस्टम में, इन कॉलबैक के तरीकों को लागू करके, ये इनपुट इवेंट Activity या फ़ोकस किया गया View (आपको यह करना चाहिए इसके लिए कॉलबैक लागू करें Activity या View, लेकिन दोनों नहीं):

  • Activity से:
  • View से:
    • onGenericMotionEvent(android.view.MotionEvent)

      जॉयस्टिक मूवमेंट जैसे सामान्य मोशन इवेंट को प्रोसेस करने के लिए कहा जाता है.

    • onKeyDown(int, android.view.KeyEvent)

      इसे गेमपैड जैसी फ़िज़िकल बटन को दबाने के लिए कहा जाता है या डी-पैड बटन.

    • onKeyUp(int, android.view.KeyEvent)

      इसे गेमपैड जैसी फ़िज़िकल बटन रिलीज़ करने के लिए कहा जाता है या डी-पैड बटन.

सुझाया गया तरीका यह है कि खास View ऑब्जेक्ट होता है, जिससे उपयोगकर्ता इंटरैक्ट करता है. जानकारी पाने के लिए, कॉलबैक से मिले इन ऑब्जेक्ट की जांच करें मिलने वाले इनपुट इवेंट के टाइप के बारे में यहां बताया गया है:

KeyEvent
दिशा के बारे में बताने वाला ऑब्जेक्ट पैड (डी-पैड) और गेमपैड बटन इवेंट. मुख्य इवेंट के साथ एक कुंजी कोड, जो ट्रिगर किए गए किसी खास बटन के बारे में बताता हो, जैसे DPAD_DOWN या BUTTON_A. आपको यह जानकारी मिल सकती है getKeyCode() पर कॉल करके या डिजिटल बटन से कुंजी का कोड इवेंट कॉलबैक, जैसे कि onKeyDown().
MotionEvent
एक ऑब्जेक्ट जो जॉयस्टिक और शोल्डर ट्रिगर से मिले इनपुट के बारे में बताता है हलचल. मोशन इवेंट के साथ एक ऐक्शन कोड और ऐक्सिस की वैल्यू शामिल करें. कार्रवाई कोड, होने वाले स्थिति बदलाव की जानकारी देता है जैसे कि जॉयस्टिक को हिलाया जा रहा हो. ऐक्सिस की वैल्यू, पोज़िशन और अन्य किसी खास फ़िज़िकल कंट्रोल के लिए हलचल से जुड़ी प्रॉपर्टी, जैसे कि AXIS_X या AXIS_RTRIGGER. कार्रवाई कोड पाने के लिए, getAction() को कॉल करके और ऐक्सिस की वैल्यू को getAxisValue() को कॉल किया जा रहा है.

इस लेसन में बताया गया है कि आम तौर पर इस्तेमाल किए जाने वाले टाइप के इनपुट कैसे मैनेज किए जा सकते हैं फ़िज़िकल कंट्रोल (गेमपैड के बटन, डायरेक्शनल पैड, और जॉयस्टिक) का इस्तेमाल करके, गेम स्क्रीन पर View कॉलबैक के तरीके और प्रोसेस जारी है KeyEvent और MotionEvent ऑब्जेक्ट.

यह पुष्टि करना कि गेम कंट्रोलर कनेक्ट है

इनपुट इवेंट की रिपोर्टिंग के दौरान, Android किसी गैर-गेम कंट्रोलर डिवाइस से आए इवेंट और उन इवेंट के बीच एक गेम कंट्रोलर का इस्तेमाल किया जाता है. उदाहरण के लिए, टचस्क्रीन की मदद से की जाने वाली कार्रवाई X को दिखाने वाला AXIS_X इवेंट स्पर्श सतह का निर्देशांक है, लेकिन जॉयस्टिक AXIS_X इवेंट, जो जॉयस्टिक की X पोज़िशन दिखाता है. अगर आपने आपके गेम को, गेम-कंट्रोलर के इनपुट को हैंडल करना है, तो पहले आपको यह कि इनपुट इवेंट, काम के सोर्स टाइप से मिला है.

यह पुष्टि करने के लिए कि कनेक्ट किया गया इनपुट डिवाइस, गेम कंट्रोलर है कुल बिट फ़ील्ड पाने के लिए getSources() उस डिवाइस पर समर्थित इनपुट स्रोत प्रकार. इसके बाद, यह देखा जा सकता है कि निम्न फ़ील्ड सेट हैं:

  • SOURCE_GAMEPAD का सोर्स टाइप बताता है कि इनपुट डिवाइस में गेमपैड बटन हों (उदाहरण के लिए, BUTTON_A). ध्यान दें कि इस स्रोत टाइप यह पूरी तरह से नहीं बताता कि गेम कंट्रोलर में डी-पैड बटन हैं या नहीं, हालांकि, ज़्यादातर गेमपैड में आम तौर पर दिशा बदलने के कंट्रोल होते हैं.
  • SOURCE_DPAD का सोर्स टाइप बताता है कि इनपुट डिवाइस में डी-पैड बटन हैं (उदाहरण के लिए, DPAD_UP).
  • SOURCE_JOYSTICK का सोर्स टाइप इससे पता चलता है कि इनपुट डिवाइस में ऐनालॉग कंट्रोल स्टिक है. उदाहरण के लिए, जॉयस्टिक जो AXIS_X पर गतिविधि रिकॉर्ड करती है और AXIS_Y).

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

Kotlin

fun getGameControllerIds(): List<Int> {
    val gameControllerDeviceIds = mutableListOf<Int>()
    val deviceIds = InputDevice.getDeviceIds()
    deviceIds.forEach { deviceId ->
        InputDevice.getDevice(deviceId).apply {

            // Verify that the device has gamepad buttons, control sticks, or both.
            if (sources and InputDevice.SOURCE_GAMEPAD == InputDevice.SOURCE_GAMEPAD
                    || sources and InputDevice.SOURCE_JOYSTICK == InputDevice.SOURCE_JOYSTICK) {
                // This device is a game controller. Store its device ID.
                gameControllerDeviceIds
                        .takeIf { !it.contains(deviceId) }
                        ?.add(deviceId)
            }
        }
    }
    return gameControllerDeviceIds
}

Java

public ArrayList<Integer> getGameControllerIds() {
    ArrayList<Integer> gameControllerDeviceIds = new ArrayList<Integer>();
    int[] deviceIds = InputDevice.getDeviceIds();
    for (int deviceId : deviceIds) {
        InputDevice dev = InputDevice.getDevice(deviceId);
        int sources = dev.getSources();

        // Verify that the device has gamepad buttons, control sticks, or both.
        if (((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD)
                || ((sources & InputDevice.SOURCE_JOYSTICK)
                == InputDevice.SOURCE_JOYSTICK)) {
            // This device is a game controller. Store its device ID.
            if (!gameControllerDeviceIds.contains(deviceId)) {
                gameControllerDeviceIds.add(deviceId);
            }
        }
    }
    return gameControllerDeviceIds;
}

इसके अलावा, हो सकता है कि आप अलग-अलग इनपुट क्षमताओं की जांच करना चाहें जो कनेक्ट किए गए गेम कंट्रोलर के साथ काम करता है. यह उपयोगी हो सकता है, उदाहरण के लिए, अगर आपको यह अनुमति देनी होगी कि आपका गेम, फ़िज़िकल कंट्रोल के सेट में मौजूद इनपुट का ही इस्तेमाल करे समझना.

यह पता लगाने के लिए कि कोई खास कुंजी कोड या ऐक्सिस कोड, कनेक्ट किए गए डिवाइस के साथ काम करता है या नहीं गेम कंट्रोलर, इन तकनीकों का इस्तेमाल करें:

  • Android 4.4 (एपीआई लेवल 19) या उसके बाद के वर्शन में, यह तय किया जा सकता है कि कुंजी कोड यह कॉल, कनेक्ट किए गए गेम कंट्रोलर पर काम करता है hasKeys(int...).
  • Android 3.1 (एपीआई लेवल 12) या उसके बाद के वर्शन में, सभी उपलब्ध ऐक्सिस देखे जा सकते हैं पहली बार कॉल करने पर, कनेक्ट किए गए गेम कंट्रोलर के साथ काम करता है getMotionRanges(). इसके बाद, हर InputDevice.MotionRange ऑब्जेक्ट लौटाया गया, कॉल करें ऐक्सिस आईडी पाने के लिए, getAxis().

गेमपैड के बटन दबाने की प्रक्रिया

पहली इमेज में दिखाया गया है कि Android कैसे कुंजी कोड और ऐक्सिस की वैल्यू को फ़िज़िकल वैल्यू से मैप करता है ज़्यादातर गेम कंट्रोलर पर कंट्रोल मिलता है.

पहला डायग्राम. सामान्य गेम कंट्रोलर की प्रोफ़ाइल.

इमेज में मौजूद कॉलआउट के बारे में यहां बताया गया है:

गेमपैड के बटन दबाने पर जनरेट होने वाले सामान्य कुंजी कोड में ये शामिल हैं BUTTON_A, BUTTON_B, BUTTON_SELECT, और BUTTON_START. कुछ गेम डी-पैड क्रॉसबार के बीच में दबाने पर कंट्रोलर भी DPAD_CENTER कुंजी कोड को ट्रिगर करता है. आपका गेम getKeyCode() पर कॉल करके, डिजिटल बटन के कोड की जांच कर सकता है या मुख्य इवेंट कॉलबैक से मिलता है, जैसे कि onKeyDown(), और अगर यह किसी ऐसे इवेंट को दिखाता है जो आपके गेम के लिए काम का है, तो गेम ऐक्शन. पहले टेबल में, सबसे आम गेमपैड के बटन.

टेबल 1. गेमपैड के लिए सुझाई गई गेम कार्रवाइयां बटन.

गेम ऐक्शन बटन का कुंजी कोड
मुख्य मेन्यू में गेम शुरू करें या गेम के दौरान रोकें/अनपॉज़ करें BUTTON_START*
मेन्यू दिखाएं BUTTON_SELECT* और KEYCODE_MENU*
Android के वापस जाएं नेविगेशन के व्यवहार के बारे में, इसमें बताया गया है नेविगेशन डिज़ाइन पढ़ें. KEYCODE_BACK
मेन्यू में पिछले आइटम पर वापस जाएं BUTTON_B
चुने गए विकल्प की पुष्टि करें या गेम में मुख्य कार्रवाई करें BUTTON_A और DPAD_CENTER

* आपके गेम को इस तरह का कॉन्टेंट इस्तेमाल नहीं करना चाहिए: बटन.

सलाह: कॉन्फ़िगरेशन स्क्रीन उपलब्ध कराएं इससे उपयोगकर्ता, गेम कंट्रोलर की मैपिंग को अपने हिसाब से तय कर सकते हैं गेम ऐक्शन.

नीचे दिया गया स्निपेट यह बताता है कि किस तरह बदला जा सकता है onKeyDown() से BUTTON_A को जोड़ना और DPAD_CENTER बटन दबाए गए एक गेम ऐक्शन करते हैं.

Kotlin

class GameView(...) : View(...) {
    ...

    override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
        var handled = false
        if (event.source and InputDevice.SOURCE_GAMEPAD == InputDevice.SOURCE_GAMEPAD) {
            if (event.repeatCount == 0) {
                when (keyCode) {
                    // Handle gamepad and D-pad button presses to navigate the ship
                    ...

                    else -> {
                        keyCode.takeIf { isFireKey(it) }?.run {
                            // Update the ship object to fire lasers
                            ...
                            handled = true
                        }
                    }
                }
            }
            if (handled) {
                return true
            }
        }
        return super.onKeyDown(keyCode, event)
    }

    // Here we treat Button_A and DPAD_CENTER as the primary action
    // keys for the game.
    private fun isFireKey(keyCode: Int): Boolean =
            keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_BUTTON_A
}

Java

public class GameView extends View {
    ...

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        boolean handled = false;
        if ((event.getSource() & InputDevice.SOURCE_GAMEPAD)
                == InputDevice.SOURCE_GAMEPAD) {
            if (event.getRepeatCount() == 0) {
                switch (keyCode) {
                    // Handle gamepad and D-pad button presses to
                    // navigate the ship
                    ...

                    default:
                         if (isFireKey(keyCode)) {
                             // Update the ship object to fire lasers
                             ...
                             handled = true;
                         }
                     break;
                }
            }
            if (handled) {
                return true;
            }
        }
        return super.onKeyDown(keyCode, event);
    }

    private static boolean isFireKey(int keyCode) {
        // Here we treat Button_A and DPAD_CENTER as the primary action
        // keys for the game.
        return keyCode == KeyEvent.KEYCODE_DPAD_CENTER
                || keyCode == KeyEvent.KEYCODE_BUTTON_A;
    }
}

ध्यान दें: Android 4.2 (एपीआई) पर और उससे कम है, तो सिस्टम यह तय करता है कि BUTTON_A का Android ऐप्लिकेशन डिफ़ॉल्ट रूप से, वापस जाएं बटन. अगर आपका ऐप्लिकेशन इन Android डिवाइस पर काम करता है तो पक्का करें कि मुख्य गेम के तौर पर BUTTON_A कार्रवाई. मौजूदा Android SDK का पता लगाने के लिए देखें, तो Build.VERSION.SDK_INT वैल्यू.

डायरेक्शनल पैड इनपुट प्रोसेस करें

4-वे डायरेक्शनल पैड (डी-पैड) कई गेम में आम तौर पर इस्तेमाल किया जाने वाला फ़िज़िकल कंट्रोल है कंट्रोलर. Android की रिपोर्ट के मुताबिक, डी-पैड पर अप और डाउन ऐरो को इस तरह दबाया जाता है रेंज के साथ AXIS_HAT_Y इवेंट -1.0 (ऊपर) से 1.0 (नीचे) तक और डी-पैड लेफ़्ट या राइट ऐरो को इस तरह दबाया जाता है -1.0 की रेंज वाले AXIS_HAT_X इवेंट (बाएं) से 1.0 (दाएं) तक.

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

दूसरी टेबल. डी-पैड बटन के लिए गेम से जुड़ी सुझाई गई डिफ़ॉल्ट कार्रवाइयां कोड और हैट ऐक्सिस की वैल्यू.

गेम ऐक्शन डी-पैड कुंजी कोड Hat ऐक्सिस कोड
ऊपर ले जाएं KEYCODE_DPAD_UP AXIS_HAT_Y (0 से -1.0 तक की वैल्यू के लिए)
नीचे ले जाएं KEYCODE_DPAD_DOWN AXIS_HAT_Y (0 से 1.0 तक की वैल्यू के लिए)
बाईं ओर ले जाएं KEYCODE_DPAD_LEFT AXIS_HAT_X (0 से -1.0 तक की वैल्यू के लिए)
दाईं ओर ले जाएं KEYCODE_DPAD_RIGHT AXIS_HAT_X (0 से 1.0 तक की वैल्यू के लिए)

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

Kotlin

class Dpad {

    private var directionPressed = -1 // initialized to -1

    fun getDirectionPressed(event: InputEvent): Int {
        if (!isDpadDevice(event)) {
            return -1
        }

        // If the input event is a MotionEvent, check its hat axis values.
        (event as? MotionEvent)?.apply {

            // Use the hat axis value to find the D-pad direction
            val xaxis: Float = event.getAxisValue(MotionEvent.AXIS_HAT_X)
            val yaxis: Float = event.getAxisValue(MotionEvent.AXIS_HAT_Y)

            directionPressed = when {
                // Check if the AXIS_HAT_X value is -1 or 1, and set the D-pad
                // LEFT and RIGHT direction accordingly.
                xaxis.compareTo(-1.0f) == 0 -> Dpad.LEFT
                xaxis.compareTo(1.0f) == 0 -> Dpad.RIGHT
                // Check if the AXIS_HAT_Y value is -1 or 1, and set the D-pad
                // UP and DOWN direction accordingly.
                yaxis.compareTo(-1.0f) == 0 -> Dpad.UP
                yaxis.compareTo(1.0f) == 0 -> Dpad.DOWN
                else -> directionPressed
            }
        }
        // If the input event is a KeyEvent, check its key code.
        (event as? KeyEvent)?.apply {

            // Use the key code to find the D-pad direction.
            directionPressed = when(event.keyCode) {
                KeyEvent.KEYCODE_DPAD_LEFT -> Dpad.LEFT
                KeyEvent.KEYCODE_DPAD_RIGHT -> Dpad.RIGHT
                KeyEvent.KEYCODE_DPAD_UP -> Dpad.UP
                KeyEvent.KEYCODE_DPAD_DOWN -> Dpad.DOWN
                KeyEvent.KEYCODE_DPAD_CENTER ->  Dpad.CENTER
                else -> directionPressed
            }
        }
        return directionPressed
    }

    companion object {
        internal const val UP = 0
        internal const val LEFT = 1
        internal const val RIGHT = 2
        internal const val DOWN = 3
        internal const val CENTER = 4

        fun isDpadDevice(event: InputEvent): Boolean =
            // Check that input comes from a device with directional pads.
            event.source and InputDevice.SOURCE_DPAD != InputDevice.SOURCE_DPAD
    }
}

Java

public class Dpad {
    final static int UP       = 0;
    final static int LEFT     = 1;
    final static int RIGHT    = 2;
    final static int DOWN     = 3;
    final static int CENTER   = 4;

    int directionPressed = -1; // initialized to -1

    public int getDirectionPressed(InputEvent event) {
        if (!isDpadDevice(event)) {
           return -1;
        }

        // If the input event is a MotionEvent, check its hat axis values.
        if (event instanceof MotionEvent) {

            // Use the hat axis value to find the D-pad direction
            MotionEvent motionEvent = (MotionEvent) event;
            float xaxis = motionEvent.getAxisValue(MotionEvent.AXIS_HAT_X);
            float yaxis = motionEvent.getAxisValue(MotionEvent.AXIS_HAT_Y);

            // Check if the AXIS_HAT_X value is -1 or 1, and set the D-pad
            // LEFT and RIGHT direction accordingly.
            if (Float.compare(xaxis, -1.0f) == 0) {
                directionPressed =  Dpad.LEFT;
            } else if (Float.compare(xaxis, 1.0f) == 0) {
                directionPressed =  Dpad.RIGHT;
            }
            // Check if the AXIS_HAT_Y value is -1 or 1, and set the D-pad
            // UP and DOWN direction accordingly.
            else if (Float.compare(yaxis, -1.0f) == 0) {
                directionPressed =  Dpad.UP;
            } else if (Float.compare(yaxis, 1.0f) == 0) {
                directionPressed =  Dpad.DOWN;
            }
        }

        // If the input event is a KeyEvent, check its key code.
        else if (event instanceof KeyEvent) {

           // Use the key code to find the D-pad direction.
            KeyEvent keyEvent = (KeyEvent) event;
            if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_LEFT) {
                directionPressed = Dpad.LEFT;
            } else if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_RIGHT) {
                directionPressed = Dpad.RIGHT;
            } else if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_UP) {
                directionPressed = Dpad.UP;
            } else if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_DOWN) {
                directionPressed = Dpad.DOWN;
            } else if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_CENTER) {
                directionPressed = Dpad.CENTER;
            }
        }
        return directionPressed;
    }

    public static boolean isDpadDevice(InputEvent event) {
        // Check that input comes from a device with directional pads.
        if ((event.getSource() & InputDevice.SOURCE_DPAD)
             != InputDevice.SOURCE_DPAD) {
             return true;
         } else {
             return false;
         }
     }
}

इस हेल्पर क्लास का इस्तेमाल, अपने गेम में किसी भी जगह किया जा सकता है डी-पैड इनपुट (उदाहरण के लिए, onGenericMotionEvent() या onKeyDown() कॉलबैक).

उदाहरण के लिए:

Kotlin

private val dpad = Dpad()
...
override fun onGenericMotionEvent(event: MotionEvent): Boolean {
    if (Dpad.isDpadDevice(event)) {
        when (dpad.getDirectionPressed(event)) {
            Dpad.LEFT -> {
                // Do something for LEFT direction press
                ...
                return true
            }
            Dpad.RIGHT -> {
                // Do something for RIGHT direction press
                ...
                return true
            }
            Dpad.UP -> {
                // Do something for UP direction press
                ...
                return true
            }
            ...
        }
    }

    // Check if this event is from a joystick movement and process accordingly.
    ...
}

Java

Dpad dpad = new Dpad();
...
@Override
public boolean onGenericMotionEvent(MotionEvent event) {

    // Check if this event if from a D-pad and process accordingly.
    if (Dpad.isDpadDevice(event)) {

       int press = dpad.getDirectionPressed(event);
       switch (press) {
            case LEFT:
                // Do something for LEFT direction press
                ...
                return true;
            case RIGHT:
                // Do something for RIGHT direction press
                ...
                return true;
            case UP:
                // Do something for UP direction press
                ...
                return true;
            ...
        }
    }

    // Check if this event is from a joystick movement and process accordingly.
    ...
}

जॉयस्टिक मूवमेंट प्रोसेस करें

जब खिलाड़ी अपने गेम कंट्रोलर पर जॉयस्टिक मूव करते हैं, तो Android MotionEvent जिसमें ACTION_MOVE कार्रवाई कोड और अपडेट किया गया जॉयस्टिक के ऐक्सिस की पोज़िशन. आपका गेम इनसे मिले डेटा का इस्तेमाल कर सकता है MotionEvent ताकि यह पता चल सके कि इसे जॉयस्टिक मूव किया गया है या नहीं क्या हुआ.

ध्यान दें कि जॉयस्टिक मोशन इवेंट, कई हलचल के सैंपल को एक साथ बैच में भेज सकते हैं एक ऑब्जेक्ट के अंदर हो सकता है. MotionEvent ऑब्जेक्ट में यह शामिल है प्रत्येक जॉयस्टिक अक्ष के लिए वर्तमान स्थिति और साथ ही साथ कई ऐतिहासिक हर ऐक्सिस की जगह बदलें. ऐक्शन कोड ACTION_MOVE (जैसे कि जॉयस्टिक मूवमेंट) के साथ मोशन इवेंट की रिपोर्ट करते समय, Android ऐक्सिस की वैल्यू तय करें. किसी ऐक्सिस की ऐतिहासिक वैल्यू में, अलग-अलग वैल्यू का सेट, जो मौजूदा ऐक्सिस वैल्यू से पुराना है और हाल ही में किसी पिछले मोशन इवेंट में रिपोर्ट की गई वैल्यू. ज़्यादा जानकारी के लिए, ज़्यादा जानकारी के लिए MotionEvent रेफ़रंस.

गेम को ज़्यादा सटीक तरीके से रेंडर करने के लिए, पुरानी जानकारी का इस्तेमाल किया जा सकता है जॉयस्टिक इनपुट के आधार पर ऑब्जेक्ट की गतिविधि. यहां की यात्रा पर हूं वर्तमान और ऐतिहासिक मानों को पुनर्प्राप्त करने के लिए, getAxisValue() या getHistoricalAxisValue(). आपको डेमोग्राफ़िक (उम्र, लिंग, आय, शिक्षा वगैरह) के हिसाब से, कॉल करके जॉयस्टिक इवेंट में पॉइंट पाएं getHistorySize().

नीचे दिया गया स्निपेट दिखाता है कि जॉयस्टिक इनपुट प्रोसेस करने के लिए, onGenericMotionEvent() कॉलबैक. पहले आपको किसी ऐक्सिस की पुरानी वैल्यू प्रोसेस करने के बाद, उसकी मौजूदा पोज़िशन को प्रोसेस किया जाता है.

Kotlin

class GameView(...) : View(...) {

    override fun onGenericMotionEvent(event: MotionEvent): Boolean {

        // Check that the event came from a game controller
        return if (event.source and InputDevice.SOURCE_JOYSTICK == InputDevice.SOURCE_JOYSTICK
                && event.action == MotionEvent.ACTION_MOVE) {

            // Process the movements starting from the
            // earliest historical position in the batch
            (0 until event.historySize).forEach { i ->
                // Process the event at historical position i
                processJoystickInput(event, i)
            }

            // Process the current movement sample in the batch (position -1)
            processJoystickInput(event, -1)
            true
        } else {
            super.onGenericMotionEvent(event)
        }
    }
}

Java

public class GameView extends View {

    @Override
    public boolean onGenericMotionEvent(MotionEvent event) {

        // Check that the event came from a game controller
        if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) ==
                InputDevice.SOURCE_JOYSTICK &&
                event.getAction() == MotionEvent.ACTION_MOVE) {

            // Process all historical movement samples in the batch
            final int historySize = event.getHistorySize();

            // Process the movements starting from the
            // earliest historical position in the batch
            for (int i = 0; i < historySize; i++) {
                // Process the event at historical position i
                processJoystickInput(event, i);
            }

            // Process the current movement sample in the batch (position -1)
            processJoystickInput(event, -1);
            return true;
        }
        return super.onGenericMotionEvent(event);
    }
}

जॉयस्टिक इनपुट का उपयोग करने से पहले, आपको यह तय करना होगा कि जॉयस्टिक बीच में, तो उसके अनुसार इसकी धुरी की गति की गणना करें. आम तौर पर जॉयस्टिक फ़्लैट एरिया होता है. इसका मतलब है कि (0,0) निर्देशांक के पास वैल्यू की रेंज है जिस पर ऐक्सिस को सेंटर माना जाता है. यदि अक्ष का मान Android फ़्लैट एरिया में आता है, आपको कंट्रोलर को आराम (इसका मतलब है कि दोनों ऐक्सिस से स्थिर रहना.

नीचे दिया गया स्निपेट एक सहायक विधि दिखाता है, जो साथ-साथ गति की गणना करती है हर ऐक्सिस पर. आपने इस हेल्पर को processJoystickInput() तरीके में शुरू किया है जिनकी जानकारी नीचे दी गई है.

Kotlin

private fun getCenteredAxis(
        event: MotionEvent,
        device: InputDevice,
        axis: Int,
        historyPos: Int
): Float {
    val range: InputDevice.MotionRange? = device.getMotionRange(axis, event.source)

    // A joystick at rest does not always report an absolute position of
    // (0,0). Use the getFlat() method to determine the range of values
    // bounding the joystick axis center.
    range?.apply {
        val value: Float = if (historyPos < 0) {
            event.getAxisValue(axis)
        } else {
            event.getHistoricalAxisValue(axis, historyPos)
        }

        // Ignore axis values that are within the 'flat' region of the
        // joystick axis center.
        if (Math.abs(value) > flat) {
            return value
        }
    }
    return 0f
}

Java

private static float getCenteredAxis(MotionEvent event,
        InputDevice device, int axis, int historyPos) {
    final InputDevice.MotionRange range =
            device.getMotionRange(axis, event.getSource());

    // A joystick at rest does not always report an absolute position of
    // (0,0). Use the getFlat() method to determine the range of values
    // bounding the joystick axis center.
    if (range != null) {
        final float flat = range.getFlat();
        final float value =
                historyPos < 0 ? event.getAxisValue(axis):
                event.getHistoricalAxisValue(axis, historyPos);

        // Ignore axis values that are within the 'flat' region of the
        // joystick axis center.
        if (Math.abs(value) > flat) {
            return value;
        }
    }
    return 0;
}

इन सभी को एक साथ मिलाकर, यहां बताया गया है कि जॉयस्टिक मूवमेंट को कैसे प्रोसेस किया जा सकता है आपका गेम:

Kotlin

private fun processJoystickInput(event: MotionEvent, historyPos: Int) {

    val inputDevice = event.device

    // Calculate the horizontal distance to move by
    // using the input value from one of these physical controls:
    // the left control stick, hat axis, or the right control stick.
    var x: Float = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_X, historyPos)
    if (x == 0f) {
        x = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_HAT_X, historyPos)
    }
    if (x == 0f) {
        x = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_Z, historyPos)
    }

    // Calculate the vertical distance to move by
    // using the input value from one of these physical controls:
    // the left control stick, hat switch, or the right control stick.
    var y: Float = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_Y, historyPos)
    if (y == 0f) {
        y = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_HAT_Y, historyPos)
    }
    if (y == 0f) {
        y = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_RZ, historyPos)
    }

    // Update the ship object based on the new x and y values
}

Java

private void processJoystickInput(MotionEvent event,
        int historyPos) {

    InputDevice inputDevice = event.getDevice();

    // Calculate the horizontal distance to move by
    // using the input value from one of these physical controls:
    // the left control stick, hat axis, or the right control stick.
    float x = getCenteredAxis(event, inputDevice,
            MotionEvent.AXIS_X, historyPos);
    if (x == 0) {
        x = getCenteredAxis(event, inputDevice,
                MotionEvent.AXIS_HAT_X, historyPos);
    }
    if (x == 0) {
        x = getCenteredAxis(event, inputDevice,
                MotionEvent.AXIS_Z, historyPos);
    }

    // Calculate the vertical distance to move by
    // using the input value from one of these physical controls:
    // the left control stick, hat switch, or the right control stick.
    float y = getCenteredAxis(event, inputDevice,
            MotionEvent.AXIS_Y, historyPos);
    if (y == 0) {
        y = getCenteredAxis(event, inputDevice,
                MotionEvent.AXIS_HAT_Y, historyPos);
    }
    if (y == 0) {
        y = getCenteredAxis(event, inputDevice,
                MotionEvent.AXIS_RZ, historyPos);
    }

    // Update the ship object based on the new x and y values
}

ज़्यादा बेहतर सुविधाओं वाले गेम कंट्रोलर को सपोर्ट करने के लिए बस एक जॉयस्टिक के अलावा अन्य सुविधाएँ उपलब्ध कराने के लिए, इन सबसे सही तरीकों को अपनाएं:

  • ड्यूअल कंट्रोलर स्टिक हैंडल करें. कई गेम कंट्रोलर के पास बाईं और दाईं जॉयस्टिक. बाईं स्टिक के लिए, Android हॉरिज़ॉन्टल मूवमेंट को AXIS_X इवेंट के तौर पर रिपोर्ट करता है और AXIS_Y इवेंट के तौर पर वर्टिकल मूवमेंट. दाईं स्टिक के लिए, Android हॉरिज़ॉन्टल मूवमेंट इस तरह रिपोर्ट करता है: AXIS_Z इवेंट और वर्टिकल मूवमेंट इस तरह से हैं AXIS_RZ इवेंट. पक्का करें कि आपने दोनों कंट्रोलर आपके कोड में चिपक जाते हैं.
  • शोल्डर ट्रिगर को हैंडल करने से रोकने के लिए, अन्य इनपुट दें तरीका है). कुछ कंट्रोलर के कंधों पर बायां और दायां कंधा होता है ट्रिगर हैं. अगर ये ट्रिगर मौजूद हैं, तो Android, बाईं ओर दिए गए ट्रिगर को दबाने की सूचना देता है AXIS_LTRIGGER इवेंट के तौर पर और राइट ट्रिगर दबाएं AXIS_RTRIGGER इवेंट. Android पर 4.3 (एपीआई लेवल 18), एक ऐसा कंट्रोलर है जो AXIS_LTRIGGER ने AXIS_BRAKE ऐक्सिस के लिए एक जैसी वैल्यू. कॉन्टेंट बनाने AXIS_RTRIGGER और AXIS_GAS. Android, सभी ऐनालॉग ट्रिगर की रिपोर्ट करता है सामान्य वैल्यू के साथ 0.0 (रिलीज़ की गई) से 1.0 (पूरी तरह दबाया गया) तक दबाता है. नहीं सभी कंट्रोलर के पास ट्रिगर होते हैं. इसलिए, खिलाड़ियों को वे परफ़ॉर्म करने की अनुमति दें अन्य बटनों की मदद से गेम की कार्रवाइयां.