Wprowadzanie myszą

Z tego artykułu dowiesz się, jak wdrożyć obsługę myszy w Grach Google Play na PC na w których tryb tłumaczenia danych wejściowych nie zapewnia idealnego efektu.

Gracze na PC mają zwykle klawiaturę i mysz zamiast ekranu dotykowego, dzięki czemu trzeba wziąć pod uwagę, czy gra obsługuje się w trybie myszy. Domyślnie Gry Google Play na PC przekształcają dowolne zdarzenie kliknięcia lewym przyciskiem myszy w jedno zdarzenie zdarzenie kliknięcia. Jest to tzw. „tryb translacji danych wejściowych”.

Ten tryb zapewnia funkcjonalność gry po wprowadzeniu kilku zmian, ale nie zapewniają graczom PC wrażenia z środowisko natywnego. Zalecamy gdy zastosujesz poniższe rozwiązania:

  • Stany najechania kursorem w przypadku menu kontekstowych zamiast naciśnięcia i przytrzymania działania
  • Kliknij prawym przyciskiem myszy, aby wyświetlić alternatywne działania, które są wykonywane po przytrzymaniu lub w kontekście menu
  • Szukaj myszką w przypadku gier akcji FPP lub Trójosobowych zamiast po naciśnięciu zdarzenie przeciągania

Aby korzystać z wzorców interfejsu powszechnych na komputerach PC, musisz wyłączyć wprowadzanie danych wejściowych. trybu tłumaczenia.

Obsługa danych wejściowych w Grach Google Play na PC jest taka sama jak ChromeOS Zmiany dotyczące komputerów PC gry na Androida.

Wyłącz tryb translacji danych wejściowych

W pliku AndroidManifest.xml zadeklaruj funkcję android.hardware.type.pc. Oznacza to, że gra używa sprzętu komputerowego i wyłącza tłumaczenie danych wejściowych i trybu uzyskiwania zgody. Dodatkowo dodanie atrybutu required="false" sprawi, że gra będzie mogła wciąż mogą być instalowane 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 prawidłową przy uruchamianiu gry. Jeśli chcesz uruchomić emulator programisty, wykonaj te czynności: kliknij ikonę na pasku aplikacji prawym przyciskiem myszy, wybierz Opcje programisty, a następnie Tryb PC(KiwiMouse), który dostarcza nieprzetworzone dane wejściowe myszy.

Zrzut ekranu pokazujący „tryb PC(KiwiMouse)” wybrane w menu kontekstowym

Gdy to zrobisz, ruch myszą będzie raportowany przez View.onGeneralMotionEvent ze źródłem SOURCE_MOUSE co wskazuje na 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łudze myszy znajdziesz w Dokumentacja ChromeOS

Obsługa ruchu myszy

Aby wykryć ruch myszą, posłuchaj urządzeń ACTION_HOVER_ENTER, ACTION_HOVER_EXIT i ACTION_HOVER_MOVE zdarzeń.

Najlepiej sprawdza się wtedy, gdy użytkownik najeżdża kursorem na przyciski lub obiekty umożliwia wyświetlenie pola podpowiedzi lub zaimplementowanie stanu najechania kursorem myszy. aby podkreślić, co gracz wybierze. 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 od dawna miały lewy i prawy przycisk myszy, co dało interaktywne elementy działania główne i dodatkowe. W grze kliknij działania, np. kliknięcie są mapowane na kliknięcie lewym przyciskiem myszy, tam gdzie dotknięcie wstrzymywanie działania klikając prawym przyciskiem myszy. Gry strategiczne czasu rzeczywistego, z których możesz też korzystać kliknij lewym przyciskiem myszy, aby zaznaczyć, i kliknij prawym przyciskiem, aby przenieść. W strzelankach FPP głównego i dodatkowego uruchomienia, klikając lewy i prawy przycisk myszy. Nieskończona gra Kliknij lewym przyciskiem myszy, aby skakać, lub kliknij prawym przyciskiem, aby użyć myślnika. Nie dodaliśmy obsługi zdarzenie środkowego kliknięcia.

Aby obsługiwać naciśnięcia przycisków, używaj ACTION_DOWN i ACTION_UP. Następnie użyj getActionButton, aby określić, który przycisk wywołał działanie, lub getButtonState, aby zobaczyć stan wszystkich przycisków.

W tym przykładzie do wyświetlenia wyniku 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 w przypadku zdarzeń 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;
});

Uchwyć przewijanie kółkiem myszy

Do powiększania zalecamy używanie kółka myszy zamiast ściągnięcia palcami. gestami lub dotykaniem i przeciąganiem obszarów przewijania w grze.

Aby odczytać wartości kółka przewijania, nasłuchuj zdarzenia ACTION_SCROLL. delta od ostatniej klatki można pobrać za pomocą parametru getAxisValue z parametrem AXIS_VSCROLL dla przesunięcia w pionie i AXIS_HSCROLL dla przesunięcia w poziomie. 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ą mieć pełną kontrolę nad kursorem myszy, np. pierwszy lub trzeci gry akcji z udziałem osób, które mapują ruch myszą na ruch kamery. Do zrobienia wyłączna kontrola nad myszą – wywołaj View.requestPointerCapture().

requestPointerCapture() działa tylko wtedy, gdy hierarchia widoków danych zawierająca Twoje jest zaznaczony. Z tego powodu nie można zarejestrować wskaźnika w onCreate oddzwonienie. Zaczekaj, aż interakcja z graczem zostanie przechwycona kursora myszy, np. podczas pracy z menu głównym, lub onWindowFocusChanged oddzwanianie. 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 zarejestrowane przez aplikację requestPointerCapture() są wysyłane do zarejestrowanego widoku 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 umożliwić graczom przechwytywanie myszy, np. wejść w interakcję z menu wstrzymania, wywołać View.releasePointerCapture().