নিয়ন্ত্রক কর্ম হ্যান্ডেল

সিস্টেম লেভেলে, Android গেম কন্ট্রোলার থেকে ইনপুট ইভেন্ট কোডগুলিকে Android কী কোড এবং অক্ষ মান হিসাবে রিপোর্ট করে। আপনার গেমে, আপনি এই কোড এবং মানগুলি পেতে পারেন এবং সেগুলিকে নির্দিষ্ট ইন-গেম অ্যাকশনগুলিতে রূপান্তর করতে পারেন৷

খেলোয়াড়রা যখন তাদের Android-চালিত ডিভাইসের সাথে একটি গেম কন্ট্রোলারকে শারীরিকভাবে সংযুক্ত করে বা তারবিহীনভাবে জোড়া দেয়, তখন সিস্টেমটি একটি ইনপুট ডিভাইস হিসাবে নিয়ামকটিকে স্বয়ংক্রিয়ভাবে সনাক্ত করে এবং এর ইনপুট ইভেন্টগুলির প্রতিবেদন করা শুরু করে৷ আপনার সক্রিয় Activity বা ফোকাসড View নিম্নলিখিত কলব্যাক পদ্ধতিগুলি প্রয়োগ করে আপনার গেমটি এই ইনপুট ইভেন্টগুলি পেতে পারে (আপনি Activity বা View জন্য কলব্যাকগুলি প্রয়োগ করা উচিত, তবে উভয় নয়):

  • Activity থেকে:
    • dispatchGenericMotionEvent(android.view. MotionEvent)

      জেনারিক মোশন ইভেন্ট যেমন জয়স্টিক মুভমেন্ট প্রক্রিয়া করার জন্য বলা হয়।

    • dispatchKeyEvent(android.view.KeyEvent)

      গেমপ্যাড বা ডি-প্যাড বোতামের প্রেস বা রিলিজের মতো গুরুত্বপূর্ণ ইভেন্টগুলি প্রক্রিয়া করার জন্য কল করা হয়।

  • 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 একটি নন-গেম কন্ট্রোলার ডিভাইস থেকে আসা ইভেন্ট এবং গেম কন্ট্রোলার থেকে আসা ইভেন্টগুলির মধ্যে পার্থক্য করে না। উদাহরণস্বরূপ, একটি টাচ স্ক্রিন অ্যাকশন একটি AXIS_X ইভেন্ট তৈরি করে যা স্পর্শ পৃষ্ঠের X স্থানাঙ্ককে উপস্থাপন করে, কিন্তু একটি জয়স্টিক একটি AXIS_X ইভেন্ট তৈরি করে যা জয়স্টিকের X অবস্থানকে উপস্থাপন করে। যদি আপনার গেমটি গেম-কন্ট্রোলার ইনপুট পরিচালনার বিষয়ে চিন্তা করে, তাহলে আপনাকে প্রথমে পরীক্ষা করা উচিত যে ইনপুট ইভেন্টটি প্রাসঙ্গিক উত্স প্রকার থেকে এসেছে।

একটি সংযুক্ত ইনপুট ডিভাইস একটি গেম কন্ট্রোলার কিনা তা যাচাই করতে, সেই ডিভাইসে সমর্থিত ইনপুট সোর্স প্রকারের একটি সম্মিলিত বিট ক্ষেত্র পেতে getSources() এ কল করুন। তারপরে আপনি নিম্নলিখিত ক্ষেত্রগুলি সেট করা আছে কিনা তা দেখতে পরীক্ষা করতে পারেন:

  • SOURCE_GAMEPAD এর একটি উৎস প্রকার নির্দেশ করে যে ইনপুট ডিভাইসটিতে গেমপ্যাড বোতাম রয়েছে (উদাহরণস্বরূপ, BUTTON_A )। মনে রাখবেন যে এই উত্স প্রকারটি কঠোরভাবে নির্দেশ করে না যে গেম কন্ট্রোলারে ডি-প্যাড বোতাম আছে কিনা, যদিও বেশিরভাগ গেমপ্যাডে সাধারণত দিকনির্দেশক নিয়ন্ত্রণ থাকে।
  • একটি উৎস প্রকারের SOURCE_DPAD নির্দেশ করে যে ইনপুট ডিভাইসে D-প্যাড বোতাম রয়েছে (উদাহরণস্বরূপ, DPAD_UP )।
  • SOURCE_JOYSTICK এর একটি উত্স প্রকার নির্দেশ করে যে ইনপুট ডিভাইসটিতে অ্যানালগ নিয়ন্ত্রণ স্টিক রয়েছে (উদাহরণস্বরূপ, একটি জয়স্টিক যা AXIS_X এবং AXIS_Y সাথে গতিবিধি রেকর্ড করে)।

নিম্নলিখিত কোড স্নিপেট একটি সহায়ক পদ্ধতি দেখায় যা আপনাকে সংযুক্ত ইনপুট ডিভাইসগুলি গেম কন্ট্রোলার কিনা তা পরীক্ষা করতে দেয়৷ যদি তাই হয়, পদ্ধতিটি গেম কন্ট্রোলারের জন্য ডিভাইস আইডি পুনরুদ্ধার করে। তারপরে আপনি আপনার গেমের একটি প্লেয়ারের সাথে প্রতিটি ডিভাইস আইডি সংযুক্ত করতে পারেন এবং প্রতিটি সংযুক্ত প্লেয়ারের জন্য আলাদাভাবে গেম অ্যাকশন প্রক্রিয়া করতে পারেন৷ একই অ্যান্ড্রয়েড ডিভাইসে একই সাথে সংযুক্ত একাধিক গেম কন্ট্রোলারকে সমর্থন করার বিষয়ে আরও জানতে, একাধিক গেম কন্ট্রোলার সমর্থন করুন দেখুন।

কোটলিন

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
}

জাভা

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 (API স্তর 19) বা উচ্চতর, আপনি hasKeys(int...) কল করে একটি সংযুক্ত গেম কন্ট্রোলারে একটি কী কোড সমর্থিত কিনা তা নির্ধারণ করতে পারেন।
  • Android 3.1 (API স্তর 12) বা উচ্চতর, আপনি প্রথমে getMotionRanges() কল করে একটি সংযুক্ত গেম কন্ট্রোলারে সমর্থিত সমস্ত উপলব্ধ অক্ষ খুঁজে পেতে পারেন৷ তারপরে, প্রতিটি InputDevice.MotionRange অবজেক্টে ফিরে, তার অক্ষ ID পেতে getAxis() কল করুন।

গেমপ্যাড বোতাম টিপে প্রক্রিয়া করুন

চিত্র 1 দেখায় কিভাবে Android বেশিরভাগ গেম কন্ট্রোলারের শারীরিক নিয়ন্ত্রণে কী কোড এবং অক্ষ মানগুলিকে ম্যাপ করে।

চিত্র 1. একটি জেনেরিক গেম কন্ট্রোলারের প্রোফাইল।

চিত্রের কলআউটগুলি নিম্নলিখিত উল্লেখ করে:

গেমপ্যাড বোতাম টিপে তৈরি হওয়া সাধারণ কী কোডগুলির মধ্যে রয়েছে BUTTON_A , BUTTON_B , BUTTON_SELECT , এবং BUTTON_START ৷ কিছু গেম কন্ট্রোলার DPAD_CENTER কী কোড ট্রিগার করে যখন ডি-প্যাড ক্রসবারের কেন্দ্রে চাপ দেওয়া হয়। আপনার গেমটি getKeyCode() কল করে বা কী ইভেন্ট কলব্যাক যেমন onKeyDown() থেকে কী কোড পরীক্ষা করতে পারে এবং যদি এটি আপনার গেমের সাথে প্রাসঙ্গিক কোনো ইভেন্টের প্রতিনিধিত্ব করে, তাহলে এটিকে একটি গেম অ্যাকশন হিসাবে প্রক্রিয়া করুন। সারণি 1 সর্বাধিক সাধারণ গেমপ্যাড বোতামগুলির জন্য প্রস্তাবিত গেম অ্যাকশনগুলির তালিকা করে৷

সারণী 1. গেমপ্যাড বোতামগুলির জন্য প্রস্তাবিত গেম অ্যাকশন।

গেম অ্যাকশন বোতাম কী কোড
প্রধান মেনুতে খেলা শুরু করুন, অথবা খেলা চলাকালীন বিরতি/আনপজ করুন BUTTON_START *
ডিসপ্লে মেনু BUTTON_SELECT * এবং KEYCODE_MENU *
ন্যাভিগেশন ডিজাইন গাইডে বর্ণিত Android ব্যাক নেভিগেশন আচরণের মতোই৷ KEYCODE_BACK
একটি মেনুতে একটি পূর্ববর্তী আইটেম ফিরে নেভিগেট করুন BUTTON_B
নির্বাচন নিশ্চিত করুন, বা প্রাথমিক গেম অ্যাকশন সঞ্চালন করুন BUTTON_A এবং DPAD_CENTER

* আপনার গেমটি স্টার্ট, সিলেক্ট বা মেনু বোতামের উপস্থিতির উপর নির্ভর করবে না।

টিপ: ব্যবহারকারীদের গেম অ্যাকশনের জন্য তাদের নিজস্ব গেম কন্ট্রোলার ম্যাপিংগুলিকে ব্যক্তিগতকৃত করার অনুমতি দেওয়ার জন্য আপনার গেমে একটি কনফিগারেশন স্ক্রীন প্রদান করার কথা বিবেচনা করুন৷

নিচের স্নিপেটটি দেখায় যে আপনি কীভাবে onKeyDown() ওভাররাইড করতে পারেন একটি গেম অ্যাকশনের সাথে BUTTON_A এবং DPAD_CENTER বোতাম টিপতে।

কোটলিন

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
}

জাভা

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 (API স্তর 17) এবং তার নিচের ক্ষেত্রে, সিস্টেমটি ডিফল্টরূপে BUTTON_A Android Back কী হিসাবে বিবেচনা করে৷ আপনার অ্যাপ্লিকেশান যদি এই Android সংস্করণগুলিকে সমর্থন করে, তাহলে নিশ্চিত করুন যে BUTTON_A প্রাথমিক গেম অ্যাকশন হিসাবে বিবেচনা করুন৷ ডিভাইসে বর্তমান Android SDK সংস্করণ নির্ধারণ করতে, Build.VERSION.SDK_INT মান পড়ুন।

নির্দেশমূলক প্যাড ইনপুট প্রক্রিয়া করুন

4-ওয়ে ডিরেকশনাল প্যাড (ডি-প্যাড) অনেক গেম কন্ট্রোলারের একটি সাধারণ শারীরিক নিয়ন্ত্রণ। অ্যান্ড্রয়েড -1.0 (উপর) থেকে 1.0 (নিচে) রেঞ্জ সহ AXIS_HAT_Y ইভেন্ট হিসাবে ডি-প্যাড UP এবং DOWN প্রেস রিপোর্ট করে এবং -1.0 (বাম) থেকে 1.0 (ডাউন) এর রেঞ্জ সহ AXIS_HAT_X ইভেন্ট হিসাবে ডি-প্যাড বাম বা ডান প্রেস করে ডান)।

কিছু কন্ট্রোলার পরিবর্তে একটি কী কোড দিয়ে ডি-প্যাড প্রেসের রিপোর্ট করে। যদি আপনার গেমটি ডি-প্যাড প্রেসের বিষয়ে যত্নশীল হয়, তাহলে আপনাকে সারণি 2-এ সুপারিশকৃত হ্যাট অক্ষ ইভেন্ট এবং ডি-প্যাড কী কোডগুলিকে একই ইনপুট ইভেন্ট হিসাবে বিবেচনা করা উচিত।

সারণি 2. ডি-প্যাড কী কোড এবং হ্যাট অক্ষ মানগুলির জন্য প্রস্তাবিত ডিফল্ট গেম অ্যাকশন।

গেম অ্যাকশন ডি-প্যাড কী কোড হ্যাট অক্ষ কোড
উপরে সরান 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 মানের জন্য)

নিম্নলিখিত কোড স্নিপেট একটি সহায়ক শ্রেণী দেখায় যা আপনাকে ডি-প্যাডের দিকনির্দেশ নির্ধারণের জন্য একটি ইনপুট ইভেন্ট থেকে হ্যাট অক্ষ এবং কী কোড মান পরীক্ষা করতে দেয়।

কোটলিন

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

জাভা

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() কলব্যাকগুলিতে) আপনি আপনার গেমটিতে এই সহায়ক শ্রেণীটি ব্যবহার করতে পারেন।

যেমন:

কোটলিন

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.
    ...
}

জাভা

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() কলব্যাককে ওভাররাইড করতে পারেন। আপনার প্রথমে একটি অক্ষের জন্য ঐতিহাসিক মানগুলি প্রক্রিয়া করা উচিত, তারপর তার বর্তমান অবস্থান প্রক্রিয়া করা উচিত।

কোটলিন

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

জাভা

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) স্থানাঙ্কের কাছাকাছি মানগুলির একটি পরিসীমা যেখানে অক্ষটিকে কেন্দ্রীভূত বলে মনে করা হয়। যদি অ্যান্ড্রয়েডের দ্বারা রিপোর্ট করা অক্ষের মান সমতল এলাকার মধ্যে পড়ে, তাহলে আপনার কন্ট্রোলারকে বিশ্রামে রাখা উচিত (অর্থাৎ উভয় অক্ষ বরাবর গতিহীন)।

নীচের স্নিপেটটি একটি সহায়ক পদ্ধতি দেখায় যা প্রতিটি অক্ষ বরাবর আন্দোলন গণনা করে। আপনি নিচে আরো বর্ণিত processJoystickInput() পদ্ধতিতে এই সাহায্যকারীকে ডাকবেন।

কোটলিন

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
}

জাভা

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

সবকিছু একসাথে রেখে, আপনি কীভাবে আপনার গেমে জয়স্টিক মুভমেন্ট প্রক্রিয়া করতে পারেন তা এখানে:

কোটলিন

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
}

জাভা

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 ইভেন্ট হিসাবে রিপোর্ট করে৷ আপনার কোডে উভয় কন্ট্রোলার স্টিক হ্যান্ডেল নিশ্চিত করুন।
  • কাঁধের ট্রিগার প্রেসগুলি পরিচালনা করুন (এবং নিশ্চিত করুন যে আপনার গেম AXIS_ এবং KEYCODE_BUTTON_ ইভেন্টগুলির সাথে কাজ করে)। কিছু কন্ট্রোলারের বাম এবং ডান কাঁধের ট্রিগার রয়েছে। যখন এই ট্রিগারগুলি উপস্থিত থাকে, তখন তারা একটি AXIS_*TRIGGER বা KEYCODE_BUTTON_*2 ইভেন্ট বা উভয়ই নির্গত করে। বাম ট্রিগারের জন্য, এটি হবে AXIS_LTRIGGER এবং KEYCODE_BUTTON_L2 । সঠিক ট্রিগারের জন্য এটি হবে AXIS_RTRIGGER এবং KEYCODE_BUTTON_R2 । অক্ষ ইভেন্টগুলি শুধুমাত্র তখনই ঘটে যখন ট্রিগারটি 0 এবং 1 এর মধ্যে মানগুলির একটি পরিসীমা নির্গত করে এবং কিছু নিয়ামক অক্ষ ইভেন্টগুলি ছাড়াও অ্যানালগ আউটপুট বোতাম ইভেন্টগুলি নির্গত করে। সমস্ত সাধারণ গেম কন্ট্রোলারের সাথে সামঞ্জস্যপূর্ণ থাকার জন্য গেমগুলিকে অবশ্যই AXIS_ এবং KEYCODE_BUTTON_ উভয় ইভেন্টকে সমর্থন করতে হবে, তবে কোনো কন্ট্রোলার উভয়ের রিপোর্ট করলে আপনার গেমপ্লের জন্য সবচেয়ে অর্থপূর্ণ ইভেন্টটিকে পছন্দ করুন৷ Android 4.3 (API স্তর 18) এবং উচ্চতর, একটি AXIS_LTRIGGER তৈরি করে এমন একটি কন্ট্রোলারও AXIS_BRAKE অক্ষের জন্য একটি অভিন্ন মান রিপোর্ট করে৷ AXIS_RTRIGGER এবং AXIS_GAS ক্ষেত্রেও একই কথা সত্য। অ্যান্ড্রয়েড 0.0 (রিলিজ) থেকে 1.0 (পুরোপুরি চাপানো) পর্যন্ত একটি স্বাভাবিক মান সহ সমস্ত অ্যানালগ ট্রিগার প্রেসের রিপোর্ট করে৷
  • অনুকরণ করা পরিবেশে নির্দিষ্ট আচরণ এবং সমর্থন ভিন্ন হতে পারে । অনুকরণ করা প্ল্যাটফর্ম, যেমন Google Play Games , হোস্ট অপারেটিং সিস্টেমের ক্ষমতার উপর ভিত্তি করে আচরণে কিছুটা ভিন্ন হতে পারে। উদাহরণস্বরূপ, কিছু কন্ট্রোলার যেগুলি AXIS_ এবং KEYCODE_BUTTON_ উভয় ইভেন্ট নির্গত করে শুধুমাত্র AXIS_ ইভেন্টগুলি নির্গত করে, এবং কিছু কন্ট্রোলারের সমর্থন সম্পূর্ণরূপে অনুপস্থিত হতে পারে৷