Mauseingabe

In diesem Artikel wird beschrieben, wie die Mauseingabe für Google Play Spiele auf dem PC für Spiele implementiert wird, bei denen der Eingabeübersetzungsmodus kein ideales Spielererlebnis bietet.

PC-Spieler haben in der Regel eine Tastatur und eine Maus, keinen Touchscreen. Daher ist es wichtig, zu überlegen, ob Ihr Spiel die Mauseingabe unterstützt. Standardmäßig wandelt Google Play Spiele auf dem PC jedes Mausklickereignis mit der linken Maustaste in ein einzelnes virtuelles Tippen-Ereignis um. Dies wird als „Eingabeübersetzungsmodus“ bezeichnet.

In diesem Modus ist Ihr Spiel zwar mit wenigen Änderungen funktionsfähig, bietet aber keinen nativen Look für PC-Spieler. Dazu empfehlen wir Folgendes:

  • Hover-Zustände für Kontextmenüs, anstatt Aktionen durch Gedrückthalten gedrückt zu halten
  • Klicken Sie mit der rechten Maustaste, um alternative Aktionen aufzurufen, die beim langen Drücken oder in einem Kontextmenü ausgeführt werden.
  • Mauslook für Actionspiele aus der Ego- oder Third-Person-Perspektive anstelle eines Drücken-und-Ziehen-Ereignisses

Zur Unterstützung von auf PCs gängigen UI-Mustern müssen Sie den Eingabeübersetzungsmodus deaktivieren.

Die Eingabebehandlung für Google Play Spiele auf dem PC entspricht der von ChromeOS. Die Änderungen, die die Unterstützung von PCs ermöglichen, verbessern Ihr Spiel auch für alle Android-Nutzer.

Übersetzungsmodus für die Eingabe deaktivieren

Deklarieren Sie in der Datei AndroidManifest.xml die android.hardware.type.pc-Funktion. Das bedeutet, dass Ihr Spiel PC-Hardware verwendet und der Modus für die Eingabeübersetzung deaktiviert ist. Außerdem kann Ihr Spiel so auch auf Smartphones und Tablets ohne Maus installiert werden.required="false" Beispiel:

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

Die Produktionsversion von Google Play Spiele auf dem PC wechselt beim Starten eines Spiels in den richtigen Modus. Wenn Sie den Entwickleremulator verwenden, müssen Sie mit der rechten Maustaste auf das Symbol in der Taskleiste klicken, Entwickleroptionen und dann PC-Modus(KiwiMouse) auswählen, um die Rohmauseingaben zu erhalten.

Screenshot, in dem im Kontextmenü „PC-Modus(KiwiMouse)“ ausgewählt ist

Danach wird die Mausbewegung von View.onGenericMotionEvent mit der Quelle SOURCE_MOUSE gemeldet, um anzugeben, 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 zum Umgang mit der Mauseingabe finden Sie in der ChromeOS-Dokumentation.

Mausbewegungen verarbeiten

Warten Sie zum Erkennen von Mausbewegungen die Ereignisse ACTION_HOVER_ENTER, ACTION_HOVER_EXIT und ACTION_HOVER_MOVE.

Diese Funktion eignet sich am besten, um zu erkennen, wenn der Nutzer den Mauszeiger auf Schaltflächen oder Objekte in einem Spiel bewegt. So können Sie ein Hinweisfeld anzeigen oder einen Mauszeigerstatus implementieren, um hervorzuheben, was ein Spieler auswählen wird. Beispiel:

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

Maustasten handhaben

PCs haben seit langem sowohl die linke als auch die rechte Maustaste, sodass interaktive Elemente sowohl primäre als auch sekundäre Aktionen haben. In einem Spiel sollten Tippaktionen wie das Tippen auf eine Schaltfläche dem Linksklick zugeordnet werden, während Aktionen wie „Tippen und halten“ am besten mit dem Rechtsklick ausgeführt werden. In Echtzeit-Strategiespielen können Sie auch mit der linken Maustaste auswählen und mit der rechten Maustaste bewegen. In Ego-Shootern werden die primäre und sekundäre Schussabgabe möglicherweise der linken und rechten Maustaste zugewiesen. Ein unendlicher Runner könnte mit Linksklick springen und Rechtsklick zum Springen. Das Ereignis „Mitte klicken“ wird nicht unterstützt.

Verwenden Sie ACTION_DOWN und ACTION_UP, um Tastendrücke zu verarbeiten. Verwenden Sie dann getActionButton, um zu ermitteln, welche Schaltfläche die Aktion ausgelöst hat, oder getButtonState, um den Status aller Schaltflächen abzurufen.

In diesem Beispiel wird ein Enum 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 dem Mausrad verarbeiten

Wir empfehlen, zum Zoomen das Scrollrad der Maus anstelle von Auseinander- und Zusammenziehen der Finger zu verwenden oder Scrollbereiche in Ihrem Spiel zu berühren und zu ziehen.

Zum Lesen der Scrollrad-Werte warten Sie auf das ACTION_SCROLL-Ereignis. Das Delta seit dem letzten Frame kann mit getAxisValue mit AXIS_VSCROLL für den vertikalen Versatz und AXIS_HSCROLL für den horizontalen Versatz abgerufen werden. Beispiel:

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 Mauszeiger vollständig übernommen werden, z. B. bei Actionspielen in der ersten oder dritten Person, bei denen die Mausbewegung der Kamerabewegung zugeordnet wird. Wenn Sie die Maus exklusiv steuern möchten, drücken Sie View.requestPointerCapture().

requestPointerCapture() funktioniert nur, wenn die Ansichtshierarchie, die Ihre Ansicht enthält, hervorgehoben ist. Aus diesem Grund können Sie im onCreate-Callback keine Zeigererfassung abrufen. Du solltest entweder auf eine Spielerinteraktion warten, um den Mauszeiger zu erfassen, z. B. bei der Interaktion mit dem Hauptmenü, oder den Callback onWindowFocusChanged verwenden. Beispiel:

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 gesendet, die OnCapturedPointerListener registriert hat. Beispiel:

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

Rufe View.releasePointerCapture() auf, um die exklusive Mausaufnahme zu veröffentlichen, damit Spieler beispielsweise mit einem Pausenmenü interagieren können.