Google Play Games is in open beta.

Saisies à la souris

Stay organized with collections Save and categorize content based on your preferences.

Cet article explique comment implémenter la compatibilité de la souris pour les jeux dans lesquels Google Play Jeux n'offre pas une expérience satisfaisante avec le mode de conversion des entrées.

Les joueurs sur PC disposent généralement d'un clavier et d'une souris plutôt que d'un écran tactile. Il est donc important de déterminer si votre jeu est compatible avec la saisie à la souris. Par défaut, Google Play Jeux convertit tout événement de clic gauche en un événement virtuel unique. C'est ce que nous appelons le "mode de conversion des entrées".

Bien que ce mode rende votre jeu fonctionnel avec peu de modifications, il n'offre pas une expérience intuitive aux joueurs de PC. Nous vous recommandons donc d'implémenter les éléments suivants :

  • États de pointage de souris pour les menus contextuels plutôt que les appuis de manière prolongée
  • Possibilité d'effectuer un clic droit pour afficher d'autres actions qui se produisent lorsqu'on appuie de manière prolongée ou dans un menu contextuel
  • Contrôle direct de la caméra à la souris dans les jeux d'action à la première ou à la troisième personne (plutôt que d'utiliser des événements de déplacement)

Pour prendre en charge les modèles d'interface utilisateur courants sur les PC, vous devez désactiver le mode de conversion des entrées.

La gestion des entrées pour Google Play Jeux est identique à celle de ChromeOS. Les modifications apportées pour les PC améliorent votre jeu pour tous les joueurs Android.

Désactiver le mode de conversion des entrées

Dans votre fichier AndroidManifest.xml, déclarez la fonctionnalité android.hardware.type.pc. Cela indique que votre jeu utilise du matériel PC et désactive le mode de conversion des entrées. De plus, l'ajout de required="false" permet de s'assurer que votre jeu peut toujours être installé sur des appareils sans souris, comme les téléphones et les tablettes. Exemple :

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

La version de production de Google Play Jeux passe au mode approprié au lancement du jeu. Lorsque vous exécutez l'émulateur de développeur, vous devez faire un clic droit sur l'icône de la barre des tâches, sélectionner Developer Options (Options pour les développeurs), puis Relative (Relatif) pour recevoir les données brutes de la souris.

Capture d'écran de l'élément "Relative" sélectionné dans le menu contextuel

Après cela, le mouvement de la souris est signalé par View.onGenericMotionEvent, la source SOURCE_MOUSE indiquant qu'il s'agit d'un événement de souris.

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

Pour en savoir plus sur la gestion des saisies à la souris, consultez la documentation Chrome OS.

Gérer les mouvements de la souris

Pour détecter les mouvements de souris, écoutez les événements ACTION_HOVER_ENTER, ACTION_HOVER_EXIT et ACTION_HOVER_MOVE.

Ces événements sont particulièrement utiles pour détecter si l'utilisateur pointe la souris sur des boutons ou des objets d'un jeu, ce qui vous permet d'afficher un indicateur ou d'implémenter un état de pointage avec la souris pour mettre en évidence les éléments qu'un joueur s'apprête à sélectionner. Exemple :

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

Gérer les boutons de la souris

Les PC disposent depuis longtemps de souris à deux boutons, gauche et droit, qui permettent d'effectuer, respectivement, une action primaire et secondaire sur les éléments interactifs. Dans un jeu, il est plus naturel d'utiliser le bouton gauche pour les clics simples, tandis que le clic droit se prête mieux aux actions avec appui prolongé. Dans les jeux de stratégie en temps réel, vous pouvez associer le clic gauche à l'action d'effectuer une sélection et le clic droit aux déplacements. Les jeux de tir à la première personne peuvent attribuer des mode de tir principal et secondaire, respectivement, aux clics gauche et droit. Un jeu de course infini peut utiliser le clic gauche pour les sauts et le droit pour les accélérations.

Pour gérer les boutons de souris, utilisez ACTION_DOWN et ACTION_UP. Utilisez ensuite getActionButton pour déterminer quel bouton a déclenché l'action ou getButtonState pour obtenir l'état de tous les boutons.

Dans cet exemple, une énumération permet d'afficher le résultat de getActionButton :

Kotlin

enum class MouseButton {
   LEFT,
   RIGHT,
   MIDDLE,
   UNKNOWN;
   companion object {
       fun fromMotionEvent(motionEvent: MotionEvent): MouseButton {
           return when (motionEvent.actionButton) {
               MotionEvent.BUTTON_PRIMARY -> LEFT
               MotionEvent.BUTTON_SECONDARY -> RIGHT
               MotionEvent.BUTTON_TERTIARY -> MIDDLE
               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;
            case MotionEvent.BUTTON_TERTIARY:
                return MouseButton.MIDDLE;
            default:
                return MouseButton.UNKNOWN;
        }
    }
}

Dans cet exemple, l'action est gérée de la même manière que les événements de pointage :

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

Gérer le défilement à l'aide de la molette de la souris

Nous vous conseillons d'utiliser la molette de la souris pour les gestes de type "pincer pour zoomer" ou "appuyer et faire glisser" pour les zones de défilement dans votre jeu.

Pour lire les valeurs de la molette, écoutez l'événement ACTION_SCROLL. Le delta depuis la dernière image peut être obtenu à l'aide de getAxisValue avec AXIS_VSCROLL pour le déplacement vertical et AXIS_HSCROLL pour le déplacement horizontal. Exemple :

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

Capturer la saisie à la souris

Certains jeux doivent entièrement contrôler le curseur de la souris. C'est le cas des jeux d'action à la première ou à la troisième personne, qui mappent le mouvement de la caméra sur le mouvement de la souris. Pour contrôler totalement la souris, appelez View.requestPointerCapture().

requestPointerCapture() ne fonctionne que lorsque la hiérarchie des vues qui contient votre vue est sélectionnée. Pour cette raison, vous ne pouvez pas acquérir la capture du pointeur dans le rappel onCreate. Attendez que l'interaction du joueur capture le pointeur de la souris, par exemple pour interagir avec le menu principal, ou utilisez le rappel onWindowFocusChanged. Exemple :

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

Les événements capturés par requestPointerCapture() sont acheminés vers le OnCapturedPointerListener enregistré. Exemple :

Kotlin

gameView.setOnCapturedPointerListener { _, motionEvent ->
    Log.d("MA", "${motionEvent.x}, ${motionEvent.y}, ${motionEvent.actionButton}")
    true
}

Java

gameView.setOnCapturedPointerListener((view, motionEvent) -> {
    Log.d("MA", motionEvent.getX() + ", " + motionEvent.getY() + ", " + motionEvent.getActionButton());
    return true;
});

Pour suspendre la capture exclusive par la souris, par exemple pour permettre aux joueurs d'interagir avec un menu de mise en pause, appelez View.releasePointerCapture().