মাউস ইনপুট

এই বিষয়ে, ইনপুট ট্রান্সলেশন মোড যেখানে প্লেয়ারদের আদর্শ অভিজ্ঞতা প্রদান করে না, সেখানে গেমের জন্য পিসি (PC)-তে Google Play Games-এ কীভাবে মাউস ইনপুট প্রয়োগ করতে হয় তা বলা হয়েছে।

পিসি (PC) প্লেয়ারদের সাধারণত টাচস্ক্রিনের পরিবর্তে কীবোর্ড ও মাউস থাকে, তাই আপনার গেমে মাউস ইনপুট কাজ করে কিনা তা বিবেচনা করা গুরুত্বপূর্ণ। সাধারণত, পিসি (PC)-তে Google Play Games মাউসের যেকোনও লেফ্ট-ক্লিক ইভেন্টকে একটি ভার্চুয়াল ট্যাপ ইভেন্টে কনভার্ট করে। এটি "ইনপুট অনুবাদ মোড" হিসেবে পরিচিত।

এই মোড আপনার গেমকে অল্প কিছু পরিবর্তনের মাধ্যমে কার্যকরী করে তুললেও, এটি পিসি (PC) প্লেয়ারদের নেটিভ-ফিলিং অভিজ্ঞতা প্রদান করে না। এর জন্য, আমরা সাজেস্ট করি যে আপনি নিম্নলিখিত বিষয়গুলি প্রয়োগ করুন:

  • প্রেস করে ধরে রাখার অ্যাকশনের পরিবর্তে কনটেক্সট মেনুর জন্য হোভার স্টেট
  • বেশিক্ষণ প্রেস করলে বা কোনও প্রসঙ্গ মেনুতে বিকল্প অ্যাকশন দেখতে ডানদিকের বোতামে ক্লিক করুন
  • প্রেস করে ড্র্যাগ করার ইভেন্টের পরিবর্তে ফার্স্ট বা থার্ড পার্সন অ্যাকশন গেমের জন্য মাউসলুক

পিসি (PC)-তে সাধারণ UI প্যাটার্ন কাজ করানোর জন্য আপনাকে ইনপুট ট্রান্সলেশন মোড বন্ধ করতে হবে।

পিসি (PC)-তে Google Play Games-এর ইনপুট হ্যান্ডলিং ChromeOS-এর মতো। পিসি (PC)-তে কাজ করে এমন পরিবর্তনগুলি সব Android প্লেয়ারদের জন্য গেমের অভিজ্ঞতাও উন্নত করে।

ইনপুট অনুবাদ মোড বন্ধ করা

আপনার AndroidManifest.xml ফাইলে, android.hardware.type.pc ফিচার ঘোষণা করুন। এর থেকে বোঝা যায় যে আপনার গেম পিসি (PC) হার্ডওয়্যার ব্যবহার করে এবং ইনপুট ট্রান্সলেশন মোড বন্ধ করে দেয়। এছাড়াও, required="false" যোগ করলে, মাউস না থাকা ফোন ও ট্যাবলেটেও আপনার গেম যে ইনস্টল করা যাবে তা নিশ্চিত করতে সাহায্য করে। যেমন:

<manifest ...>
  <uses-feature
      android:name="android.hardware.type.pc"
      android:required="false" />
  ...
</manifest>

কোনও গেম লঞ্চ করলে, পিসি (PC)-তে Google Play Games-এর প্রোডাকশন ভার্সন সঠিক মোডে পাল্টে যায়। ডেভেলপার এমুলেটরে চালানোর সময়, আপনাকে টাস্ক বার আইকনে ডানদিকের বোতামে ক্লিক করতে হবে, ডেভেলপার বিকল্প বেছে নিতে হবে এবং তারপরে কাঁচা মাউস ইনপুট পেতে পিসি মোড(KiwiMouse) বেছে নিতে হবে।

প্রসঙ্গ মেনুতে বেছে নেওয়া &quot;পিসি মোড(KiwiMouse)&quot; বিকল্পের স্ক্রিনশট

এটি করার পরে, View.onGenericMotionEvent-এর মাধ্যমে মাউসের মুভমেন্ট রিপোর্ট করা হয়, যার সোর্স হল SOURCE_MOUSE এবং এটি থেকে বোঝা যায় যে এটি একটি মাউস ইভেন্ট।

Kotlin

gameView.setOnGenericMotionListener { _, motionEvent ->
    var handled = false
    if (motionEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
        // handle the mouse event here
        handled = true
    }
    handled
}

জাভা

gameView.setOnGenericMotionListener((view, motionEvent) -> {
    if (motionEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
        // handle the mouse event here
        return true;
    }
    return false;
});

মাউস ইনপুট ম্যানেজ করা সংক্রান্ত বিবরণের জন্য, ChromeOS ডকুমেন্টেশন দেখুন।

মাউস মুভমেন্ট ম্যানেজ করা

মাউসের মুভমেন্ট শনাক্ত করতে, ACTION_HOVER_ENTER, ACTION_HOVER_EXIT এবং ACTION_HOVER_MOVE ইভেন্ট শুনুন।

এটি কোনও গেমের বোতাম বা অবজেক্টের উপর ব্যবহারকারীর হোভার করা শনাক্ত করার জন্য সবচেয়ে ভালভাবে ব্যবহার করা হয়। এর ফলে আপনি কোনও হিন্ট বক্স দেখাতে বা মাউসওভার স্টেট প্রয়োগ করতে পারেন যাতে প্লেয়ার কী বেছে নিতে চলেছেন তা হাইলাইট করা যায়। যেমন:

Kotlin

gameView.setOnGenericMotionListener { _, motionEvent ->
   var handled = false
   if (motionEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
       when(motionEvent.action) {
           MotionEvent.ACTION_HOVER_ENTER -> Log.d("MA", "Mouse entered at ${motionEvent.x}, ${motionEvent.y}")
           MotionEvent.ACTION_HOVER_EXIT -> Log.d("MA", "Mouse exited at ${motionEvent.x}, ${motionEvent.y}")
           MotionEvent.ACTION_HOVER_MOVE -> Log.d("MA", "Mouse hovered at ${motionEvent.x}, ${motionEvent.y}")
       }
       handled = true
   }

   handled
}

জাভা

gameView.setOnGenericMotionListener((view, motionEvent) -> {
    if (motionEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
        switch (motionEvent.getAction()) {
            case MotionEvent.ACTION_HOVER_ENTER:
                Log.d("MA", "Mouse entered at " + motionEvent.getX() + ", " + motionEvent.getY());
                break;
            case MotionEvent.ACTION_HOVER_EXIT:
                Log.d("MA", "Mouse exited at " + motionEvent.getX() + ", " + motionEvent.getY());
                break;
            case MotionEvent.ACTION_HOVER_MOVE:
                Log.d("MA", "Mouse hovered at " + motionEvent.getX() + ", " + motionEvent.getY());
                break;
        }
        return true;
    }
    return false;
});

মাউস বোতাম ব্যবহার করা

পিসি (PC)-তে অনেকদিন ধরেই বাঁ ও ডানদিকের মাউস বোতাম রয়েছে, যা ইন্টার‌্যাক্টিভ এলিমেন্টকে প্রাথমিক ও সেকেন্ডারি অ্যাকশন, দুটিই দেয়। গেমের মধ্যে, কোনও বোতামে ট্যাপ করার মতো অ্যাকশন বাঁদিকের-ক্লিক হিসেবে ম্যাপ করা সবচেয়ে ভালো, যেখানে টাচ করে ধরে রাখার অ্যাকশন ডানদিকের-ক্লিক হিসেবে ম্যাপ করা সবচেয়ে স্বাভাবিক। রিয়েল-টাইম স্ট্র্যাটেজি গেমে, আপনি বেছে নিতে লেফ্ট-ক্লিক এবং সরাতে রাইট-ক্লিক ব্যবহার করতে পারেন। ফার্স্ট পার্সন শুটার গেমের ক্ষেত্রে বাঁদিকে ও ডানদিকে ক্লিক করে প্রাথমিক ও সেকেন্ডারি ফায়ার করার সুবিধা অ্যাসাইন করা হতে পারে। ইনফাইনাইট রানার গেমের ক্ষেত্রে জাম্প করার জন্য লেফ্ট-ক্লিক ও ড্যাশ করার জন্য রাইট-ক্লিক ব্যবহার করা হতে পারে। আমরা মিডল-ক্লিক ইভেন্টের জন্য সহায়তা যোগ করিনি।

বোতাম প্রেস করা হ্যান্ডেল করতে, ACTION_DOWN এবং ACTION_UP ব্যবহার করুন। তারপর, কোন বোতাম অ্যাকশন ট্রিগার করেছে তা নির্ধারণ করতে getActionButton অথবা getButtonState সব বোতামের স্টেট পেতে ব্যবহার করুন।

এই উদাহরণে, getActionButton-এর ফলাফল দেখাতে সাহায্য করার জন্য একটি এনুম ব্যবহার করা হয়েছে:

Kotlin

enum class MouseButton {
   LEFT,
   RIGHT,
   UNKNOWN;
   companion object {
       fun fromMotionEvent(motionEvent: MotionEvent): MouseButton {
           return when (motionEvent.actionButton) {
               MotionEvent.BUTTON_PRIMARY -> LEFT
               MotionEvent.BUTTON_SECONDARY -> RIGHT
               else -> UNKNOWN
           }
       }
   }
}

জাভা

enum MouseButton {
    LEFT,
    RIGHT,
    MIDDLE,
    UNKNOWN;
    static MouseButton fromMotionEvent(MotionEvent motionEvent) {
        switch (motionEvent.getActionButton()) {
            case MotionEvent.BUTTON_PRIMARY:
                return MouseButton.LEFT;
            case MotionEvent.BUTTON_SECONDARY:
                return MouseButton.RIGHT;
            default:
                return MouseButton.UNKNOWN;
        }
    }
}

এই উদাহরণে, অ্যাকশনটি হোভার ইভেন্টের মতোই হ্যান্ডেল করা হয়:

Kotlin

// Handle the generic motion event
gameView.setOnGenericMotionListener { _, motionEvent ->
   var handled = false
   if (motionEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
       when (motionEvent.action) {
           MotionEvent.ACTION_BUTTON_PRESS -> Log.d(
               "MA",
               "${MouseButton.fromMotionEvent(motionEvent)} pressed at ${motionEvent.x}, ${motionEvent.y}"
           )
           MotionEvent.ACTION_BUTTON_RELEASE -> Log.d(
               "MA",
               "${MouseButton.fromMotionEvent(motionEvent)} released at ${motionEvent.x}, ${motionEvent.y}"
           )
       }
       handled = true
   }

   handled
}

জাভা

gameView.setOnGenericMotionListener((view, motionEvent) -> {
    if (motionEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
        switch (motionEvent.getAction()) {
            case MotionEvent.ACTION_BUTTON_PRESS:
                Log.d("MA", MouseButton.fromMotionEvent(motionEvent) + " pressed at " + motionEvent.getX() + ", " + motionEvent.getY());
                break;
            case MotionEvent.ACTION_BUTTON_RELEASE:
                Log.d("MA", MouseButton.fromMotionEvent(motionEvent) + " released at " + motionEvent.getX() + ", " + motionEvent.getY());
                break;
        }
        return true;
    }
    return false;
});

মাউস হুইল স্ক্রলিং ম্যানেজ করা

আমরা সাজেস্ট করি যে আপনার গেমে পিঞ্চ-টু-জুম জেসচার বা টাচ করে ড্র্যাগ করার স্ক্রল এরিয়ার পরিবর্তে মাউস স্ক্রল হুইল ব্যবহার করুন।

স্ক্রল হুইলের ভ্যালু পড়তে, ACTION_SCROLL ইভেন্ট শুনুন। শেষ ফ্রেমের পর থেকে ডেল্টা ভার্টিক্যাল অফসেটের জন্য getAxisValue-এর সাথে AXIS_VSCROLL এবং হরাইজন্টাল অফসেটের জন্য AXIS_HSCROLL ব্যবহার করে পাওয়া যেতে পারে। যেমন:

Kotlin

gameView.setOnGenericMotionListener { _, motionEvent ->
   var handled = false
   if (motionEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
       when (motionEvent.action) {
           MotionEvent.ACTION_SCROLL -> {
               val scrollX = motionEvent.getAxisValue(MotionEvent.AXIS_HSCROLL)
               val scrollY = motionEvent.getAxisValue(MotionEvent.AXIS_VSCROLL)
               Log.d("MA", "Mouse scrolled $scrollX, $scrollY")
           }
       }
       handled = true
   }
   handled
}

জাভা

gameView.setOnGenericMotionListener((view, motionEvent) -> {
    if (motionEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
        switch (motionEvent.getAction()) {
            case MotionEvent.ACTION_SCROLL:
                float scrollX = motionEvent.getAxisValue(MotionEvent.AXIS_HSCROLL);
                float scrollY = motionEvent.getAxisValue(MotionEvent.AXIS_VSCROLL);
                Log.d("MA", "Mouse scrolled " + scrollX + ", " + scrollY);
                break;
        }
        return true;
    }
    return false;
});

মাউস ইনপুট ক্যাপচার করা

কিছু গেমকে মাউস কার্সরের সম্পূর্ণ কন্ট্রোল নিতে হয়, যেমন ফার্স্ট বা থার্ড পার্সন অ্যাকশন গেম যা মাউসের মুভমেন্টকে ক্যামেরার মুভমেন্টের সাথে ম্যাপ করে। মাউসের এক্সক্লুসিভ কন্ট্রোল নিতে, View.requestPointerCapture() ইনভোক করুন।

আপনার ভিউ থাকা ভিউ হায়ারার্কিতে ফোকাস থাকলে তবেই requestPointerCapture() কাজ করে। এই কারণে, আপনি onCreate কলব্যাকে পয়েন্টার ক্যাপচার করতে পারবেন না। মাউস পয়েন্টার ক্যাপচার করার জন্য আপনাকে প্লেয়ারের ইন্টার‍্যাকশনের জন্য অপেক্ষা করতে হবে, যেমন মূল মেনুর সাথে ইন্টার‍্যাক্ট করার সময় অথবা onWindowFocusChanged কলব্যাক ব্যবহার করতে হবে। যেমন:

Kotlin

override fun onWindowFocusChanged(hasFocus: Boolean) {
   super.onWindowFocusChanged(hasFocus)

   if (hasFocus) {
       gameView.requestPointerCapture()
   }
}

জাভা

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);

    if (hasFocus) {
        View gameView = findViewById(R.id.game_view);
        gameView.requestPointerCapture();
    }
}

requestPointerCapture()-এর ক্যাপচার করা ইভেন্ট ফোকাস করা যায় এমন ভিউতে পাঠানো হয় যেটি রেজিস্টার করা হয়েছে OnCapturedPointerListener। যেমন:

Kotlin

gameView.focusable = View.FOCUSABLE
gameView.setOnCapturedPointerListener { _, motionEvent ->
    Log.d("MA", "${motionEvent.x}, ${motionEvent.y}, ${motionEvent.actionButton}")
    true
}

জাভা

gameView.setFocusable(true);
gameView.setOnCapturedPointerListener((view, motionEvent) -> {
    Log.d("MA", motionEvent.getX() + ", " + motionEvent.getY() + ", " + motionEvent.getActionButton());
    return true;
});

খেলোয়াড়দের পজ মেনুর সাথে ইন্টার‍্যাক্ট করার অনুমতি দেওয়ার মতো এক্সক্লুসিভ মাউস ক্যাপচার রিলিজ করতে, View.releasePointerCapture() ইনভোক করুন।