Topik ini membahas cara menerapkan input mouse untuk Google Play Game di PC bagi game yang mode terjemahan inputnya tidak memberikan pengalaman pemain yang ideal.
Pemain PC biasanya memiliki keyboard dan mouse, bukan layar sentuh, sehingga penting untuk mempertimbangkan apakah game Anda mengakomodasi input mouse. Secara default, Google Play Game di PC mengonversi peristiwa mouse klik kiri menjadi satu peristiwa ketuk virtual. Hal ini dikenal sebagai "mode terjemahan input".
Meskipun membuat game berfungsi dengan beberapa perubahan, mode ini tidak memberikan pengalaman game native kepada pemain PC. Untuk itu, sebaiknya Anda mengimplementasikan hal berikut:
- Status arahkan kursor untuk menu konteks, bukan tindakan tekan dan tahan
- Klik kanan untuk tindakan alternatif yang dilakukan dengan menekan lama atau di menu konteks
- Mouselook untuk game aksi orang pertama atau ketiga, bukan peristiwa tekan dan tarik
Untuk mendukung pola UI yang umum di PC, Anda harus menonaktifkan mode terjemahan input.
Penanganan input untuk Google Play Game di PC identik dengan ChromeOS. Perubahan yang mendukung PC juga meningkatkan kualitas game Anda untuk semua pemain Android.
Menonaktifkan mode terjemahan input
Dalam file AndroidManifest.xml
,
deklarasikan
fitur android.hardware.type.pc
.
Tindakan ini menunjukkan bahwa game Anda menggunakan hardware PC dan menonaktifkan mode terjemahan
input. Selain itu, menambahkan required="false"
akan membantu memastikan bahwa game Anda masih
dapat diinstal di ponsel dan tablet tanpa mouse. Contoh:
<manifest ...>
<uses-feature
android:name="android.hardware.type.pc"
android:required="false" />
...
</manifest>
Versi produksi Google Play Game di PC beralih ke mode yang benar saat game diluncurkan. Saat berjalan di emulator developer, Anda harus mengklik kanan ikon taskbar, memilih Developer Options, lalu PC mode(KiwiMouse) untuk menerima input mouse raw.
Setelah Anda melakukannya, gerakan mouse dilaporkan oleh View.onGenericMotionEvent dengan sumber SOURCE_MOUSE
yang menunjukkan bahwa peristiwa tersebut adalah peristiwa 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; });
Untuk mengetahui detail tentang cara menangani input mouse, lihat dokumentasi ChromeOS.
Menangani gerakan mouse
Untuk mendeteksi gerakan mouse, proses peristiwa ACTION_HOVER_ENTER
, ACTION_HOVER_EXIT
,
dan
ACTION_HOVER_MOVE
.
Cara ini paling baik digunakan untuk mendeteksi pengguna yang mengarahkan kursor ke tombol atau objek dalam game, yang memberi Anda kesempatan untuk menampilkan kotak petunjuk atau menerapkan status pengarahan mouse untuk menyoroti pilihan yang akan dipilih pemain. Contoh:
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; });
Menangani tombol mouse
PC memiliki tombol mouse kiri dan kanan, yang memberikan elemen interaktif baik tindakan utama maupun sekunder. Dalam game, tindakan ketuk seperti mengetuk tombol akan paling baik dipetakan untuk klik kiri dan tindakan sentuh lama akan terasa paling alami dengan klik kanan. Dalam game strategi real-time, Anda juga dapat menggunakan klik kiri untuk memilih dan klik kanan untuk bergerak. First person shooter mungkin menetapkan tugas tembak utama dan sekunder ke klik kiri dan kanan. Infinite runner dapat menggunakan klik kiri untuk melompat dan klik kanan untuk berlari. Kami belum menambahkan dukungan untuk peristiwa klik tengah.
Untuk menangani penekanan tombol, gunakan ACTION_DOWN
dan ACTION_UP
. Selanjutnya, gunakan
getActionButton
untuk menentukan tombol mana yang memicu tindakan atau
getButtonState
untuk mendapatkan status semua tombol.
Dalam contoh ini, enum digunakan untuk membantu menampilkan hasil
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; } } }
Dalam contoh ini, tindakan ditangani mirip dengan peristiwa arahkan kursor:
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; });
Menangani scrolling roda mouse
Sebaiknya gunakan roda scroll mouse sebagai ganti gestur cubit untuk memperbesar atau sentuh dan tarik area scroll dalam game Anda.
Untuk membaca nilai roda scroll, proses peristiwa ACTION_SCROLL
. Delta sejak frame terakhir dapat diambil menggunakan getAxisValue
dengan AXIS_VSCROLL
untuk offset vertikal dan AXIS_HSCROLL
untuk offset horizontal. Contoh:
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; });
Merekam input mouse
Beberapa game perlu sepenuhnya mengontrol kursor mouse seperti game aksi orang pertama atau ketiga
yang memetakan gerakan mouse ke gerakan kamera. Untuk mengambil
kontrol eksklusif mouse, panggil View.requestPointerCapture()
.
requestPointerCapture()
hanya berfungsi saat hierarki tampilan yang berisi tampilan
Anda memiliki fokus. Karena alasan ini, Anda tidak dapat memperoleh rekaman kursor di
callback onCreate
. Anda harus menunggu interaksi pemain untuk merekam
kursor mouse, seperti saat berinteraksi dengan menu utama, atau menggunakan
callback
onWindowFocusChanged
. Contoh:
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(); } }
Peristiwa yang ditangkap oleh requestPointerCapture()
akan dikirim ke tampilan yang dapat difokuskan yang mendaftarkan
OnCapturedPointerListener
. Contoh:
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; });
Untuk merilis rekaman mouse eksklusif, seperti mengizinkan pemain
berinteraksi dengan menu jeda, panggil View.releasePointerCapture()
.