মাউস ইনপুট

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

পিসি প্লেয়ারদের সাধারণত টাচস্ক্রিনের পরিবর্তে একটি কীবোর্ড এবং মাউস থাকে, আপনার গেমটি মাউস ইনপুটকে সামঞ্জস্য করে কিনা তা বিবেচনা করা গুরুত্বপূর্ণ করে তোলে। ডিফল্টরূপে, পিসিতে গুগল প্লে গেমস যেকোনো বাম-ক্লিক মাউস ইভেন্টকে একটি একক ভার্চুয়াল ট্যাপ ইভেন্টে রূপান্তর করে। এটি "ইনপুট অনুবাদ মোড" নামে পরিচিত।

যদিও এই মোডটি কিছু পরিবর্তনের সাথে আপনার গেমটিকে কার্যকরী করে তোলে, তবে এটি পিসি প্লেয়ারদের স্থানীয় অনুভূতির অভিজ্ঞতা প্রদান করে না। এর জন্য, আমরা আপনাকে নিম্নলিখিতগুলি বাস্তবায়ন করার পরামর্শ দিই:

  • প্রেস এবং হোল্ড অ্যাকশনের পরিবর্তে প্রসঙ্গ মেনুর জন্য হোভার স্টেট
  • দীর্ঘক্ষণ প্রেসে বা প্রসঙ্গ মেনুতে ঘটতে থাকা বিকল্প ক্রিয়াগুলির জন্য ডান-ক্লিক করুন
  • একটি প্রেস এবং ড্র্যাগ ইভেন্টের পরিবর্তে প্রথম বা তৃতীয় ব্যক্তির অ্যাকশন গেমগুলির জন্য মাউস দেখুন৷

পিসিতে সাধারণ UI প্যাটার্ন সমর্থন করার জন্য, আপনাকে অবশ্যই ইনপুট অনুবাদ মোড অক্ষম করতে হবে।

পিসিতে Google Play গেমগুলির জন্য ইনপুট হ্যান্ডলিং ChromeOS- এর মতোই। পিসি সমর্থন করে এমন পরিবর্তনগুলি সমস্ত অ্যান্ড্রয়েড প্লেয়ারের জন্য আপনার গেমের উন্নতি করে।

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

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

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

পিসিতে গুগল প্লে গেমসের প্রোডাকশন সংস্করণটি একটি গেম চালু হলে সঠিক মোডে সুইচ করে। বিকাশকারী এমুলেটরে চলাকালীন, আপনাকে টাস্ক বার আইকনে ডান-ক্লিক করতে হবে, বিকাশকারী বিকল্পগুলি নির্বাচন করতে হবে এবং তারপরে কাঁচা মাউস ইনপুট পেতে পিসি মোড (কিউইমাউস) নির্বাচন করতে হবে

প্রসঙ্গ মেনুতে নির্বাচিত "পিসি মোড(কিউইমাউস)"-এর স্ক্রিনশট৷

আপনি এটি করার পরে, View.onGenericMotionEvent দ্বারা SOURCE_MOUSE উৎস সহ মাউস আন্দোলনের প্রতিবেদন করা হয় যে এটি একটি মাউস ইভেন্ট।

কোটলিন

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 ইভেন্টগুলি শুনুন৷

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

কোটলিন

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

মাউস বোতাম হ্যান্ডলিং

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

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

এই উদাহরণে, getActionButton এর ফলাফল প্রদর্শন করতে সাহায্য করার জন্য একটি enum ব্যবহার করা হয়:

কোটলিন

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

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

কোটলিন

// 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 ইভেন্টের জন্য শুনুন। উল্লম্ব অফসেটের জন্য AXIS_VSCROLL এবং অনুভূমিক অফসেটের জন্য AXIS_HSCROLL সহ getAxisValue ব্যবহার করে শেষ ফ্রেমের ডেল্টা পুনরুদ্ধার করা যেতে পারে। যেমন:

কোটলিন

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 কলব্যাক ব্যবহার করুন। যেমন:

কোটলিন

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 নিবন্ধিত। যেমন:

কোটলিন

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() চালু করুন।