Z tego artykułu dowiesz się, jak wdrożyć obsługę myszy w Grach Google Play na PC w grach, w których tryb tłumaczenia wprowadzania nie zapewnia idealnego efektu.
Gracze na PC zazwyczaj korzystają z klawiatury i myszy, a nie z ekranu dotykowego, dlatego warto zastanowić się, czy Twoja gra obsługuje mysz. Domyślnie Gry Google Play na PC przekształcają każde zdarzenie kliknięcia lewym przyciskiem myszy w pojedyncze zdarzenie wirtualnego dotknięcia. Jest to tzw. „tryb tłumaczenia tekstu”.
Chociaż ten tryb umożliwia granie z niewielkimi zmianami, nie zapewnia graczom na PC wrażenia zbliżonego do natywnej rozgrywki. W tym celu zalecamy wdrożenie tych rozwiązań:
- stany kursora w menu kontekstowych zamiast działań polegających na przytrzymaniu,
- Kliknij prawym przyciskiem myszy, aby wykonać alternatywne czynności po przytrzymaniu lub w menu kontekstowym
- Mouselook w przypadku gier akcji z widokiem z poziomu pierwszej lub trzeciej osoby, a nie zdarzeń naciśnięcia i przeciągnięcia.
Aby korzystać z wzorców interfejsu często używanych na komputerach PC, musisz wyłączyć tryb tłumaczenia danych wejściowych.
Obsługa danych wejściowych w Grach Google Play na PC jest taka sama jak w ChromeOS. Zmiany, które obsługują komputery PC, poprawiają też grę dla wszystkich graczy na Androida.
Wyłączanie trybu tłumaczenia tekstu
W pliku AndroidManifest.xml
zadeklaruj android.hardware.type.pc
funkcję.
Oznacza to, że gra używa sprzętu komputerowego i wyłącza tryb tłumaczenia danych wejściowych. Dodatkowo dzięki dodaniu required="false"
możesz mieć pewność, że Twoja gra będzie nadal instalowana na telefonach i tabletach bez myszy. Na przykład:
<manifest ...>
<uses-feature
android:name="android.hardware.type.pc"
android:required="false" />
...
</manifest>
Wersja produkcyjna Gier Google Play na PC przełącza się na odpowiedni tryb, gdy uruchamiasz grę. Aby uzyskać surowe dane wejściowe z myszy, gdy emulator działa w trybie deweloperskim, kliknij prawym przyciskiem ikonę na pasku zadań, wybierz Opcje programisty, a następnie Tryb komputera(KiwiMouse).
Po wykonaniu tej czynności ruch myszy jest raportowany przez View.onGeneralMotionEvent z źródłem SOURCE_MOUSE
, które wskazuje, ż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; });
Szczegółowe informacje o obsługiwaniu danych wejściowych 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
.
Ta metoda najlepiej sprawdza się przy wykrywaniu, że użytkownik najeżdża kursorem na przyciski lub obiekty w grze. Dzięki temu można wyświetlić pole podpowiedzi lub wprowadzić stan najechania kursorem myszy, aby zaznaczyć, co gracz ma wybrać. Na 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 mają od dawna zarówno lewy, jak i prawy przycisk myszy, co umożliwia elementom interaktywnym wykonywanie zarówno działań podstawowych, jak i dodatkowych. Działanie dotykowe w grze, takie jak dotknięcie przycisku, najlepiej jest zmapowane na kliknięcie lewym przyciskiem myszy, gdzie kliknięcie prawym przyciskiem myszy sprawia, że gesty naciśnięcia i przytrzymania. W grach RTS możesz też kliknąć lewym przyciskiem myszy, aby coś wybrać, a kliknąć prawym przyciskiem, aby to przenieść. W strzelankach FPP można przypisać lewy i prawy przycisk myszy do strzelania podstawowym i dodatkowym rodzajem broni. W nieskończonym runnerze do skoku można użyć lewego przycisku myszy, a do uderzenia – prawego. Nie dodaliśmy obsługi zdarzenia środkowego kliknięcia.
Aby obsłużyć naciśnięcie przycisku, 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 wyświetlić stan wszystkich przycisków.
W tym przykładzie enum służy do wyświetlania wyniku funkcji 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; } } }
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 myszy zamiast gestów szczypania, aby powiększać obszary w grze, lub dotykania i przeciągania obszarów do przewijania.
Aby odczytać wartości kółka przewijania, nasłuchuj zdarzenia ACTION_SCROLL
. Delta od ostatniej klatki może zostać pobrana za pomocą getAxisValue
z AXIS_VSCROLL
dla przesunięcia pionowego i AXIS_HSCROLL
dla przesunięcia poziomego. Na 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 danych wejściowych z użyciem myszy
Niektóre gry muszą przejąć pełną kontrolę nad kursorem myszy, np. gry akcji z perspektywy pierwszej lub trzeciej osoby, które mapują ruch myszy na ruch kamery. Aby przejąć wyłączną kontrolę nad myszą, wywołaj View.requestPointerCapture()
.
requestPointerCapture()
działa tylko wtedy, gdy widok hierarchii zawierający Twój widok jest aktywny. Z tego powodu nie można pobrać przechwycenia wskaźnika w wywołaniu zwrotnym onCreate
. Musisz albo poczekać, aż gracz wejdzie w interakcję z wskaźnikiem myszy (np. podczas korzystania z menu głównego), albo użyć wywołania zwrotnego onWindowFocusChanged
. Na 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 rejestrowane przez requestPointerCapture()
są wysyłane do widoku z możliwością skupienia, który zarejestrował zdarzenie OnCapturedPointerListener
. Na 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 odblokować wyłączne przechwytywanie kursora, na przykład w celu umożliwienia graczom interakcji z menu pauzy, wywołaj View.releasePointerCapture()
.