الإدخال بالماوس

يتناول هذا الموضوع كيفية إدخال الماوس في برنامج "ألعاب Google Play على الكمبيوتر" على الألعاب التي لا يوفر فيها وضع ترجمة الإدخال تجربة مثالية للّاعبين.

عادةً ما يكون لدى لاعبي الكمبيوتر لوحة مفاتيح وماوس بدلاً من شاشة تعمل باللمس، مما يجعل من المهم أن تضع في اعتبارك ما إذا كانت اللعبة تتسع لإدخال الماوس أم لا. بشكل افتراضي، يحوّل برنامج "ألعاب Google Play على الكمبيوتر" أي حدث عند النقر بزر الماوس الأيسر إلى حدث واحد حدث افتراضي يعتمد على النقر يُعرف هذا باسم "وضع ترجمة الإدخال".

على الرغم من أنّ هذا الوضع يجعل لعبتك تعمل مع إجراء بعض التغييرات، لن يؤدي إلى ذلك. ستمنح اللاعبين على الكمبيوتر تجربة متكاملة. ولإجراء ذلك، ننصحك تقوم بتنفيذ ما يلي:

  • يمكنك التمرير فوق حالات قوائم السياقات بدلاً من الضغط مع الاستمرار على الإجراءات
  • انقر بزر الماوس الأيمن للحصول على الإجراءات البديلة التي تحدث عند الضغط مع الاستمرار أو في سياق القائمة
  • استخدم الماوس لألعاب الحركة من منظور البطل أو من خلال الصحافة حدث سحب

من أجل إتاحة أنماط واجهة المستخدم الشائعة على أجهزة الكمبيوتر، يجب إيقاف الإدخال وضع الترجمة.

تتطابق معالجة الإدخال في برنامج "ألعاب Google Play على الكمبيوتر" مع معالجة الإدخال في ChromeOS. التغييرات التي تدعم أجهزة الكمبيوتر الشخصية أيضًا تحسين لعبتك لجميع مشغّلات Android.

إيقاف وضع ترجمة الإدخال

في ملف AndroidManifest.xml، الإعلان عن android.hardware.type.pc الميزة. يشير ذلك إلى أنّ لعبتك تستخدم أجهزة الكمبيوتر الشخصي ويتم إيقاف ترجمة الإدخال. الحالي. بالإضافة إلى ذلك، تساعد إضافة "required="false"" في ضمان قدرة لعبتك على لا يزال يمكن تثبيتها على الهواتف والأجهزة اللوحية بدون ماوس. مثلاً:

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

يتم تبديل إصدار الإنتاج من برنامج "ألعاب Google Play على الكمبيوتر" إلى الإصدار الصحيح. عند تشغيل اللعبة. وعند تشغيلك في محاكي المطور، يلزمك النقر بزر الماوس الأيمن على رمز شريط المهام واختيار خيارات المطوّرين وضع الكمبيوتر الشخصي(KiwiMouse) لتلقي إدخالات الماوس الأولية.

لقطة شاشة تُظهر &quot;وضع الكمبيوتر الشخصي(KiwiMouse)&quot; تم اختياره في قائمة السياقات

بعد إجراء ذلك، يتم الإبلاغ عن حركة الماوس من خلال View.onGeneralMotionEvent باستخدام المصدر SOURCE_MOUSE. مما يشير إلى أنه حدث ماوس.

Kotlin

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

Java

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
}

Java

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:

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

Java

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
}

Java

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
}

Java

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

Java

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

Java

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

من أجل إطلاق لقطة حصرية للماوس، مثل السماح للاعبين التفاعل مع قائمة إيقاف مؤقت، ثم استدعاء View.releasePointerCapture().