In diesem Artikel erfahren Sie, wie Sie Mauseingaben für Google Play Spiele auf dem PC für Spiele implementieren, bei denen der Modus für die Eingabeübersetzung nicht ideal ist.
PC-Spieler haben normalerweise eine Tastatur und Maus anstelle eines Touchscreens. Daher ist es wichtig zu überlegen, ob Ihr Spiel Mauseingaben unterstützt. Standardmäßig wandelt Google Play Spiele auf dem PC jedes Ereignis mit der linken Maustaste in ein einzelnes virtuelles Tippereignis um. Dies wird als „Eingabeübersetzungsmodus“ bezeichnet.
Auch wenn dieser Modus mit nur wenigen Änderungen funktioniert, bietet er PC-Spielern kein natives Erlebnis. Dazu empfehlen wir, Folgendes zu implementieren:
- Hover-Status für Kontextmenüs anstelle von Drücken und Halten von Aktionen
- Mit der rechten Maustaste kannst du alternative Aktionen ausführen, die durch langes Drücken oder in einem Kontextmenü ausgeführt werden.
- Mouselook für First- oder Third-Person-Actionspiele anstelle von Presse- und Drag-Events
Zur Unterstützung von UI-Mustern, die auf PCs üblich sind, müssen Sie den Modus für die Eingabeübersetzung deaktivieren.
Die Eingabeverarbeitung für Google Play Spiele auf dem PC ist mit der von ChromeOS identisch. Durch die Änderungen zur Unterstützung von PCs wird dein Spiel für alle Android-Spieler verbessert.
Modus für die Eingabeübersetzung deaktivieren
Deklarieren Sie in der Datei AndroidManifest.xml
die Funktion android.hardware.type.pc
.
Dies bedeutet, dass Ihr Spiel PC-Hardware verwendet und der Eingabeübersetzungsmodus deaktiviert ist. Wenn Sie required="false"
hinzufügen, kann Ihr Spiel auch ohne Maus auf Smartphones und Tablets installiert werden. Beispiele:
<manifest ...>
<uses-feature
android:name="android.hardware.type.pc"
android:required="false" />
...
</manifest>
Die Produktionsversion von Google Play Spiele auf dem PC wechselt beim Start eines Spiels in den richtigen Modus. Wenn Sie es im Entwickleremulator ausführen, müssen Sie mit der rechten Maustaste auf das Symbol in der Taskleiste klicken, Developer Options (Entwickleroptionen) und dann PC mode(KiwiMouse) (PC-Modus (KiwiMouse)) auswählen, um die Mauseingabe im Rohformat zu erhalten.
Danach wird die Mausbewegung von View.onGenericMotionEvent gemeldet. Die Quelle SOURCE_MOUSE
weist darauf hin, dass es sich um ein Mausereignis handelt.
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; });
Weitere Informationen zur Handhabung von Mauseingaben finden Sie in der ChromeOS-Dokumentation.
Mausbewegungen steuern
Zum Erkennen von Mausbewegungen warten Sie auf die Ereignisse ACTION_HOVER_ENTER
, ACTION_HOVER_EXIT
und ACTION_HOVER_MOVE
.
Diese Methode eignet sich am besten, um zu erkennen, wie Nutzer in einem Spiel über Schaltflächen oder Objekte fahren. So haben Sie die Möglichkeit, ein Hinweisfeld anzuzeigen oder einen Mouseover-Zustand zu implementieren, um hervorzuheben, was ein Spieler auswählen wird. Beispiele:
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; });
Umgang mit Mausklicks
PCs haben schon lange sowohl die linke als auch die rechte Maustaste und ermöglichen interaktive Elemente sowohl primäre als auch sekundäre Aktionen. In einem Spiel eignen sich Tippaktionen wie das Tippen auf eine Schaltfläche am besten dem Linksklick, wenn sich Aktionen durch Berühren und Halten beim Rechtsklick am natürlichsten anfühlen. In Echtzeit-Strategiespielen können Sie sie auch mit der linken Maustaste auswählen und mit der rechten Ego-Shooter können ein primäres und sekundäres Feuer nach links und einen Rechtsklick zuweisen. Bei unendlichen Läufern wird zum Beispiel mit der linken Maustaste springen und mit der rechten Das Ereignis des mittleren Klicks wird nicht unterstützt.
Wenn du das Drücken von Tasten steuern möchtest, verwende ACTION_DOWN
und ACTION_UP
. Verwenden Sie dann getActionButton
, um festzustellen, welche Schaltfläche die Aktion ausgelöst hat, oder getButtonState
, um den Status aller Schaltflächen abzurufen.
In diesem Beispiel wird eine Aufzählung verwendet, um das Ergebnis von getActionButton
anzuzeigen:
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; } } }
In diesem Beispiel wird die Aktion ähnlich wie die Hover-Ereignisse behandelt:
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; });
Scrollen mit Mausrad
Wir empfehlen, das Scrollrad der Maus zu verwenden, anstatt sie auseinander- und zusammenzuziehen, um Touch-Gesten zu zoomen oder Scrollbereiche in Ihrem Spiel zu berühren und zu ziehen.
Warten Sie auf das Ereignis ACTION_SCROLL
, um Werte für das Scrollrad zu lesen. Das Delta seit dem letzten Frame kann mithilfe von getAxisValue
mit AXIS_VSCROLL
für den vertikalen Versatz und AXIS_HSCROLL
für den horizontalen Versatz abgerufen werden. Beispiele:
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; });
Mauseingabe erfassen
Bei einigen Spielen muss der Cursor vollständig gesteuert werden, z. B. in Ego- oder Third-Person-Action-Spielen, bei denen Mausbewegungen Kamerabewegungen zugeordnet werden. Rufen Sie View.requestPointerCapture()
auf, um die ausschließliche Kontrolle über die Maus zu übernehmen.
requestPointerCapture()
funktioniert nur, wenn die Ansichtshierarchie, die Ihre Ansicht enthält, im Fokus liegt. Aus diesem Grund können Sie die Zeigererfassung nicht im onCreate
-Callback abrufen. Sie sollten entweder auf eine Spielerinteraktion warten, um den Mauszeiger zu erfassen, z. B. bei der Interaktion mit dem Hauptmenü, oder Sie verwenden den onWindowFocusChanged
-Callback. Beispiele:
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(); } }
Von requestPointerCapture()
erfasste Ereignisse werden an die fokussierbare Ansicht weitergeleitet, in der OnCapturedPointerListener
registriert wurde. Beispiele:
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; });
Wenn Sie eine exklusive Mausaufnahme freigeben möchten, z. B. um Spielern die Interaktion mit einem Pausenmenü zu ermöglichen, rufen Sie View.releasePointerCapture()
auf.