Ten artykuł opisuje, jak zaimplementować sygnał myszy w Grach Google Play na PC w przypadku gier, w których tryb tłumaczenia danych wejściowych nie zapewnia optymalnego komfortu gry.
Gracze na PC zwykle mają klawiaturę i mysz, a nie ekran dotykowy, dlatego ważne jest, aby sprawdzić, czy Twoja gra obsługuje sygnał myszy. Domyślnie Gry Google Play na PC konwertują każde kliknięcie lewym przyciskiem myszy na pojedyncze wirtualne dotknięcie. Jest to tzw. „tryb tłumaczenia danych wejściowych”.
Chociaż ten tryb sprawia, że gra działa po wprowadzeniu niewielkich zmian, nie zapewnia graczom na PC wrażeń podobnych do tych, które dają gry na PC. Dlatego zalecamy zaimplementowanie tych funkcji:
- stany najechania kursorem w menu kontekstowych zamiast działań wykonywanych przez naciśnięcie i przytrzymanie;
- kliknięcie prawym przyciskiem myszy w celu wykonania alternatywnych działań, które są wykonywane po długim naciśnięciu lub w menu kontekstowym;
- rozglądanie się myszą w grach akcji z perspektywy pierwszej lub trzeciej osoby zamiast zdarzenia przeciągnięcia.
Aby obsługiwać wzorce interfejsu użytkownika, które są powszechne na komputerach, musisz wyłączyć tryb tłumaczenia danych wejściowych.
Obsługa danych wejściowych w Grach Google Play na PC jest identyczna jak w ChromeOS. Zmiany, które obsługują komputery, poprawiają też działanie gry na wszystkich urządzeniach z Androidem.
Wyłączanie trybu tłumaczenia danych wejściowych
W pliku AndroidManifest.xml zadeklaruj funkcję android.hardware.type.pc .
Wskazuje to, że gra korzysta ze sprzętu komputerowego, i wyłącza tryb tłumaczenia danych wejściowych. Dodanie required="false" pomaga też zapewnić, że grę można
zainstalować na telefonach i tabletach bez myszy. Przykład:
<manifest ...>
<uses-feature
android:name="android.hardware.type.pc"
android:required="false" />
...
</manifest>
Gdy gra się uruchamia, wersja produkcyjna Gier Google Play na PC przełącza się na odpowiedni tryb. Gdy korzystasz z emulatora dla deweloperów, musisz kliknąć prawym przyciskiem ikonę na pasku zadań, wybrać kolejno Opcje programisty i Tryb PC(KiwiMouse), aby otrzymywać nieprzetworzony sygnał myszy.
Gdy to zrobisz, ruch myszy będzie zgłaszany przez View.onGenericMotionEvent ze źródłem SOURCE_MOUSE
co oznacza, że jest to zdarzenie myszy.
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; });
Więcej informacji o obsłudze sygnału myszy znajdziesz w dokumentacji ChromeOS.
Obsługa ruchu myszy
Aby wykryć ruch myszy, nasłuchuj zdarzeń ACTION_HOVER_ENTER, ACTION_HOVER_EXIT i
ACTION_HOVER_MOVE.
Najlepiej używać ich do wykrywania, gdy użytkownik najedzie kursorem na przyciski lub obiekty w grze. Dzięki temu możesz wyświetlić podpowiedź lub zaimplementować stan najechania kursorem, aby wyróżnić element, który gracz ma zamiar wybrać. Przykład:
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; });
Obsługa przycisków myszy
Komputery od dawna mają lewy i prawy przycisk myszy, co umożliwia wykonywanie działań podstawowych i dodatkowych na elementach interaktywnych. W grze działania wykonywane przez dotknięcie, np. dotknięcie przycisku, najlepiej przypisać do kliknięcia lewym przyciskiem myszy, a działania wykonywane przez dotknięcie i przytrzymanie – do kliknięcia prawym przyciskiem myszy. W grach RTS możesz też używać kliknięcia lewym przyciskiem myszy do wybierania i kliknięcia prawym przyciskiem myszy do przesuwania. W strzelankach z perspektywy pierwszej osoby możesz przypisać strzelanie podstawowe i dodatkowe do kliknięcia lewym i prawym przyciskiem myszy. W grze typu infinite runner możesz używać kliknięcia lewym przyciskiem myszy do skakania i kliknięcia prawym przyciskiem myszy do sprintu. Nie dodaliśmy obsługi zdarzenia kliknięcia środkowym przyciskiem myszy.
Aby obsługiwać naciśnięcia przycisków, użyj ACTION_DOWN i ACTION_UP. Następnie użyj getActionButton, aby określić, który przycisk wywołał działanie, lub getButtonState, aby uzyskać stan wszystkich przycisków.
W tym przykładzie do wyświetlania wyniku getActionButton używamy wyliczenia:
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; } } }
W tym przykładzie działanie jest obsługiwane podobnie jak zdarzenia najechania kursorem:
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; });
Obsługa przewijania kółkiem myszy
Zalecamy używanie kółka przewijania myszy zamiast gestów uszczypnięcia w celu powiększenia lub obszarów przewijania dotykiem i przeciągnięciem.
Aby odczytać wartości kółka przewijania, nasłuchuj zdarzenia ACTION_SCROLL. Delta od ostatniej klatki można pobrać za pomocą getAxisValue z AXIS_VSCROLL dla przesunięcia pionowego i AXIS_HSCROLL dla przesunięcia poziomego. Przykład:
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; });
Przechwytywanie sygnału myszy
Niektóre gry, np. gry akcji z perspektywy pierwszej lub trzeciej osoby, które mapują ruch myszy na ruch kamery, muszą mieć pełną kontrolę nad kursorem myszy. Aby przejąć
wyłączną kontrolę nad myszą, wywołaj View.requestPointerCapture().
requestPointerCapture() działa tylko wtedy, gdy hierarchia widoków zawierająca Twój widok jest aktywna. Z tego powodu nie możesz przejąć przechwytywania wskaźnika w wywołaniu zwrotnym onCreate. Musisz poczekać na interakcję gracza, aby przechwycić
wskaźnik myszy, np. gdy gracz wchodzi w interakcję z menu główne, lub użyć
onWindowFocusChanged
wywołania zwrotnego. Przykład:
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(); } }
Zdarzenia przechwycone przez requestPointerCapture()
są wysyłane do widoku, który może uzyskać fokus i zarejestrował
OnCapturedPointerListener. Przykład:
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; });
Aby zwolnić wyłączne przechwytywanie myszy, np. aby umożliwić graczom
interakcję z menu pauzy, wywołaj View.releasePointerCapture().