Les contrôleurs comportent deux types d'actions :
KeyEventutilisé pour tout bouton avec un état binaire "activé" et "désactivé"MotionEvent: utilisé pour tout axe qui renvoie une plage de valeurs. Par exemple, de -1 à 1 pour les joysticks analogiques ou de 0 à 1 pour les gâchettes analogiques.
Vous pouvez lire ces entrées à partir de View qui comporte focus.
onGenericMotionEventest élevé pour toutMotionEvent.� et
onKeyUpsont déclenchés pourKeyEventlorsque les boutons sont enfoncés et relâchés.onKeyDown
Kotlin
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
if (event.isFromSource(SOURCE_GAMEPAD)
&& event.repeatCount == 0
) {
Log.d("GameView", "Gamepad key pressed: $keyCode")
return true
}
return super.onKeyDown(keyCode, event)
}
override fun onGenericMotionEvent(event: MotionEvent): Boolean {
if (event.isFromSource(SOURCE_JOYSTICK)) {
Log.d("GameView", "Gamepad event: $event")
return true
}
return super.onGenericMotionEvent(event)
}
Java
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (event.isFromSource(SOURCE_GAMEPAD)
&& event.getRepeatCount() == 0
) {
Log.d("GameView", "Gamepad key pressed: " + keyCode);
return true;
}
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onGenericMotionEvent(MotionEvent event) {
if (event.isFromSource(SOURCE_JOYSTICK)) {
Log.d("GameView", "Gamepad event: " + event);
return true;
}
return super.onGenericMotionEvent(event);
}
Si nécessaire, vous pouvez lire les événements directement à partir de Activity.
dispatchGenericMotionEventcollectés pourMotionEventdispatchKeyEvent. est élevé pour toutKeyEvent.
Vérifier qu'une manette de jeu est connectée
Lorsqu'il signale des événements d'entrée, Android réutilise les mêmes ID de clé ou d'axe pour différents types de périphériques d'entrée. Par exemple, une action sur un écran tactile génère un événement AXIS_X qui représente la coordonnée X de la surface tactile, tandis qu'une manette de jeu génère un événement AXIS_X qui représente la position X du stick gauche. Cela signifie que vous devez vérifier le type de source pour interpréter correctement les événements d'entrée.
Pour vérifier qu'un InputDevice connecté est une manette de jeu, utilisez la fonction supportsSource(int) :
- Un type de source
SOURCE_GAMEPADindique que le périphérique d'entrée comporte des boutons de contrôle (par exemple,KEYCODE_BUTTON_A). Notez que ce type de source n'indique pas précisément si la manette de jeu comporte des boutons de pavé directionnel, bien que la plupart des manettes disposent généralement de commandes directionnelles. - Un type de source
SOURCE_DPADindique que le périphérique d'entrée comporte des boutons directionnels (par exemple,DPAD_UP). - Un type de source
SOURCE_JOYSTICKindique que le périphérique d'entrée est équipé de joysticks analogiques (par exemple, un joystick qui enregistre les mouvements le long des axesAXIS_XetAXIS_Y).
L'extrait de code suivant montre une méthode d'assistance qui vous permet de vérifier si les périphériques d'entrée connectés sont des manettes de jeu. Si tel est le cas, la méthode récupère les ID d'appareil des manettes de jeu. Vous pouvez ensuite associer chaque ID d'appareil à un joueur de votre jeu et traiter les actions de jeu pour chaque joueur connecté séparément. Pour en savoir plus sur la prise en charge de plusieurs manettes de jeu connectées simultanément sur le même appareil Android, consultez Assurer la compatibilité avec plusieurs manettes de jeu.
Kotlin
fun getGameControllerIds(): List<Int> {
val gameControllerDeviceIds = mutableListOf<Int>()
val deviceIds = InputDevice.getDeviceIds()
deviceIds.forEach { deviceId ->
InputDevice.getDevice(deviceId)?.apply {
// Verify that the device has gamepad buttons, control sticks, or both.
if (supportsSource(SOURCE_GAMEPAD)
|| supportsSource(SOURCE_JOYSTICK)) {
// This device is a game controller. Store its device ID.
gameControllerDeviceIds
.takeIf { !it.contains(deviceId) }
?.add(deviceId)
}
}
}
return gameControllerDeviceIds
}
Java
public ArrayList<Integer> getGameControllerIds() {
ArrayList<Integer> gameControllerDeviceIds = new ArrayList<Integer>();
int[] deviceIds = InputDevice.getDeviceIds();
for (int deviceId : deviceIds) {
InputDevice dev = InputDevice.getDevice(deviceId);
if (dev == null) {
continue;
}
// Verify that the device has gamepad buttons, control sticks, or both.
if (dev.supportsSource(SOURCE_GAMEPAD) || dev.supportsSource(SOURCE_JOYSTICK)) {
// This device is a game controller. Store its device ID.
if (!gameControllerDeviceIds.contains(deviceId)) {
gameControllerDeviceIds.add(deviceId);
}
}
}
return gameControllerDeviceIds;
}
Traiter les entrées du contrôleur
Cette section décrit les types de manettes de jeu compatibles avec Android.
Les développeurs C++ doivent utiliser la bibliothèque Game Controller. Il unifie tous les contrôleurs au sous-ensemble de fonctionnalités le plus courant et fournit une interface cohérente entre eux, y compris la possibilité de détecter la disposition des boutons.
Cette figure montre à quoi un développeur de jeux Android peut s'attendre à ce qu'une manette courante ressemble sur Android.
Le tableau liste les noms et types d'événements standards pour les manettes de jeu. Pour obtenir la liste complète des événements, consultez Variantes courantes. Le système envoie les événements MotionEvent via les événements onGenericMotionEvent et KeyEvent, et les événements onKeyDown et onKeyUp.
| Saisie à la manette | KeyEvent | MotionEvent |
|---|---|---|
| 1. Pavé directionnel |
AXIS_HAT_X(entrée horizontale) AXIS_HAT_Y(entrée verticale) |
|
| 2. Joystick analogique gauche |
KEYCODE_BUTTON_THUMBL(lorsqu'il est enfoncé) |
AXIS_X(mouvement horizontal) AXIS_Y(mouvement vertical) |
| 3. Stick analogique droit |
KEYCODE_BUTTON_THUMBR(lorsqu'il est enfoncé) |
AXIS_Z(mouvement horizontal) AXIS_RZ(mouvement vertical) |
| 4. Bouton X | KEYCODE_BUTTON_X |
|
| 5. Bouton A | KEYCODE_BUTTON_A |
|
| 6. Bouton Y | KEYCODE_BUTTON_Y |
|
| 7. Bouton B | KEYCODE_BUTTON_B |
|
| 8. Gâchette haute droite |
KEYCODE_BUTTON_R1 |
|
| 9. Gâchette droite |
AXIS_RTRIGGER |
|
| 10. Gâchette gauche | AXIS_LTRIGGER |
|
| 11. Gâchette haute gauche | KEYCODE_BUTTON_L1 |
|
| 12. Démarrer | KEYCODE_BUTTON_START |
|
| 13. Sélectionner | KEYCODE_BUTTON_SELECT |
Gérer les pressions sur les boutons
Étant donné qu'Android signale les appuis sur les boutons de la manette de la même manière que les appuis sur les touches du clavier, vous devez :
- Vérifiez que l'événement provient d'un
SOURCE_GAMEPAD. - Assurez-vous de ne recevoir le bouton qu'une seule fois avec
KeyEvent.getRepeatCount(). Android enverra des événements de touche répétés comme si vous mainteniez une touche du clavier enfoncée. - Indiquez qu'un événement est géré en renvoyant
true. Transmettez les événements non gérés à
superpour vérifier que les différentes couches de compatibilité d'Android fonctionnent correctement.Kotlin
class GameView : View { // ... override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean { event.apply { var handled = false // make sure we're handling gamepad events if (isFromSource(SOURCE_GAMEPAD)) { // avoid processing the keycode repeatedly if (repeatCount == 0) { when (keyCode) { // handle the "A" button KEYCODE_BUTTON_A -> { handled = true } } // ... } } if (handled) { return true } } return super.onKeyDown(keyCode, event) } }Java
public class GameView extends View { // ... @Override public boolean onKeyDown(int keyCode, KeyEvent event) { boolean handled = false; // make sure we're handling gamepad events if (event.isFromSource(SOURCE_GAMEPAD)) { // avoid processing the keycode repeatedly if (event.getRepeatCount() == 0) { switch (keyCode) { case KEYCODE_BUTTON_A: // handle the "A" button handled = true; break; // ... } } // mark this event as handled if (handled) { return true; } } // Always do this instead of "return false" // it allows Android's input compatibility layers to work return super.onKeyDown(keyCode, event); } }
Traiter les entrées du pavé directionnel
Le pavé directionnel à quatre directions est une commande physique courante dans de nombreuses manettes de jeu. Android signale les pressions sur les boutons HAUT et BAS du pavé directionnel comme des événements AXIS_HAT_Y, avec -1.0 indiquant HAUT et 1.0 indiquant BAS. Il signale les appuis sur la croix directionnelle GAUCHE ou DROITE comme des événements AXIS_HAT_X, avec -1.0 indiquant la gauche et 1.0 indiquant la droite.
Certains contrôleurs signalent les pressions sur le pavé directionnel avec un code clé. Si votre jeu se soucie des pressions sur le pavé directionnel, vous devez traiter les événements de l'axe du chapeau et les codes de touche du pavé directionnel comme les mêmes événements d'entrée, comme recommandé dans le tableau 2.
Tableau 2. Actions de jeu par défaut recommandées pour les codes de touches du pavé directionnel et les valeurs des axes du chapeau.
| Action de jeu | Code de touche du pavé directionnel | Code Hat Axis |
|---|---|---|
| Monter | KEYCODE_DPAD_UP |
AXIS_HAT_Y (pour les valeurs comprises entre 0 et -1,0) |
| Descendre | KEYCODE_DPAD_DOWN |
AXIS_HAT_Y (pour les valeurs comprises entre 0 et 1,0) |
| Déplacer à gauche | KEYCODE_DPAD_LEFT |
AXIS_HAT_X (pour les valeurs comprises entre 0 et -1,0) |
| Déplacer à droite | KEYCODE_DPAD_RIGHT |
AXIS_HAT_X (pour les valeurs comprises entre 0 et 1,0) |
L'extrait de code suivant montre une classe d'assistance qui vous permet de vérifier les valeurs de l'axe du chapeau et du code clé d'un événement d'entrée pour déterminer la direction du pavé directionnel.
Kotlin
class Dpad {
private var directionPressed = -1 // initialized to -1
fun getDirectionPressed(event: InputEvent): Int {
if (!isDpadDevice(event)) {
return -1
}
// If the input event is a MotionEvent, check its hat axis values.
(event as? MotionEvent)?.apply {
// Use the hat axis value to find the D-pad direction
val xaxis: Float = event.getAxisValue(MotionEvent.AXIS_HAT_X)
val yaxis: Float = event.getAxisValue(MotionEvent.AXIS_HAT_Y)
directionPressed = when {
// Check if the AXIS_HAT_X value is -1 or 1, and set the D-pad
// LEFT and RIGHT direction accordingly.
xaxis.compareTo(-1.0f) == 0 -> Dpad.LEFT
xaxis.compareTo(1.0f) == 0 -> Dpad.RIGHT
// Check if the AXIS_HAT_Y value is -1 or 1, and set the D-pad
// UP and DOWN direction accordingly.
yaxis.compareTo(-1.0f) == 0 -> Dpad.UP
yaxis.compareTo(1.0f) == 0 -> Dpad.DOWN
else -> directionPressed
}
}
// If the input event is a KeyEvent, check its key code.
(event as? KeyEvent)?.apply {
// Use the key code to find the D-pad direction.
directionPressed = when(event.keyCode) {
KeyEvent.KEYCODE_DPAD_LEFT -> Dpad.LEFT
KeyEvent.KEYCODE_DPAD_RIGHT -> Dpad.RIGHT
KeyEvent.KEYCODE_DPAD_UP -> Dpad.UP
KeyEvent.KEYCODE_DPAD_DOWN -> Dpad.DOWN
KeyEvent.KEYCODE_DPAD_CENTER -> Dpad.CENTER
else -> directionPressed
}
}
return directionPressed
}
companion object {
internal const val UP = 0
internal const val LEFT = 1
internal const val RIGHT = 2
internal const val DOWN = 3
internal const val CENTER = 4
fun isDpadDevice(event: InputEvent): Boolean =
// Check that input comes from a device with directional pads.
return event.isFromSource(InputDevice.SOURCE_DPAD)
}
}
Java
public class Dpad {
final static int UP = 0;
final static int LEFT = 1;
final static int RIGHT = 2;
final static int DOWN = 3;
final static int CENTER = 4;
int directionPressed = -1; // initialized to -1
public int getDirectionPressed(InputEvent event) {
if (!isDpadDevice(event)) {
return -1;
}
// If the input event is a MotionEvent, check its hat axis values.
if (event instanceof MotionEvent) {
// Use the hat axis value to find the D-pad direction
MotionEvent motionEvent = (MotionEvent) event;
float xaxis = motionEvent.getAxisValue(MotionEvent.AXIS_HAT_X);
float yaxis = motionEvent.getAxisValue(MotionEvent.AXIS_HAT_Y);
// Check if the AXIS_HAT_X value is -1 or 1, and set the D-pad
// LEFT and RIGHT direction accordingly.
if (Float.compare(xaxis, -1.0f) == 0) {
directionPressed = Dpad.LEFT;
} else if (Float.compare(xaxis, 1.0f) == 0) {
directionPressed = Dpad.RIGHT;
}
// Check if the AXIS_HAT_Y value is -1 or 1, and set the D-pad
// UP and DOWN direction accordingly.
else if (Float.compare(yaxis, -1.0f) == 0) {
directionPressed = Dpad.UP;
} else if (Float.compare(yaxis, 1.0f) == 0) {
directionPressed = Dpad.DOWN;
}
}
// If the input event is a KeyEvent, check its key code.
else if (event instanceof KeyEvent) {
// Use the key code to find the D-pad direction.
KeyEvent keyEvent = (KeyEvent) event;
if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_LEFT) {
directionPressed = Dpad.LEFT;
} else if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_RIGHT) {
directionPressed = Dpad.RIGHT;
} else if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_UP) {
directionPressed = Dpad.UP;
} else if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_DOWN) {
directionPressed = Dpad.DOWN;
} else if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_CENTER) {
directionPressed = Dpad.CENTER;
}
}
return directionPressed;
}
public static boolean isDpadDevice(InputEvent event) {
// Check that input comes from a device with directional pads.
return event.isFromSource(InputDevice.SOURCE_DPAD);
}
}
Vous pouvez utiliser cette classe d'assistance dans votre jeu chaque fois que vous souhaitez traiter les entrées du pavé directionnel (par exemple, dans les rappels onGenericMotionEvent() ou onKeyDown()).
Exemple :
Kotlin
private val dpad = Dpad()
...
override fun onGenericMotionEvent(event: MotionEvent): Boolean {
if (Dpad.isDpadDevice(event)) {
when (dpad.getDirectionPressed(event)) {
Dpad.LEFT -> {
// Do something for LEFT direction press
...
return true
}
Dpad.RIGHT -> {
// Do something for RIGHT direction press
...
return true
}
Dpad.UP -> {
// Do something for UP direction press
...
return true
}
...
}
}
// Check if this event is from a joystick movement and process accordingly.
...
}
Java
Dpad dpad = new Dpad();
...
@Override
public boolean onGenericMotionEvent(MotionEvent event) {
// Check if this event if from a D-pad and process accordingly.
if (Dpad.isDpadDevice(event)) {
int press = dpad.getDirectionPressed(event);
switch (press) {
case LEFT:
// Do something for LEFT direction press
...
return true;
case RIGHT:
// Do something for RIGHT direction press
...
return true;
case UP:
// Do something for UP direction press
...
return true;
...
}
}
// Check if this event is from a joystick movement and process accordingly.
...
}
Traiter les mouvements du joystick
Lorsque les joueurs déplacent un joystick sur leurs manettes de jeu, Android signale un MotionEvent qui contient le code d'action ACTION_MOVE et les positions mises à jour des axes du joystick. Votre jeu peut utiliser les données fournies par MotionEvent pour déterminer si un mouvement de joystick qui l'intéresse s'est produit.
Notez que les événements de mouvement du joystick peuvent regrouper plusieurs échantillons de mouvement dans un seul objet. L'objet MotionEvent contient la position actuelle de chaque axe du joystick, ainsi que plusieurs positions historiques pour chacun d'eux. Lorsque vous signalez des événements de mouvement avec le code d'action ACTION_MOVE (comme les mouvements du joystick), Android regroupe les valeurs des axes pour plus d'efficacité. Les valeurs historiques d'un axe se composent de l'ensemble des valeurs distinctes antérieures à la valeur actuelle de l'axe et plus récentes que les valeurs signalées dans les événements de mouvement précédents. Pour en savoir plus, consultez la documentation de référence sur MotionEvent.
Pour afficher précisément le mouvement d'un objet de jeu en fonction des commandes du joystick, vous pouvez utiliser les informations historiques fournies par les objets MotionEvent.
Vous pouvez récupérer les valeurs actuelles et historiques à l'aide des méthodes suivantes :
getAxisValue()getHistoricalAxisValue()getHistorySize()(pour trouver le nombre de points historiques dans l'événement du joystick)
L'extrait suivant montre comment remplacer le rappel onGenericMotionEvent() pour traiter les entrées du joystick. Vous devez d'abord traiter les valeurs historiques d'un axe, puis sa position actuelle.
Kotlin
class GameView(...) : View(...) {
override fun onGenericMotionEvent(event: MotionEvent): Boolean {
// Check that the event came from a game controller
return if (event.source and InputDevice.SOURCE_JOYSTICK == InputDevice.SOURCE_JOYSTICK
&& event.action == MotionEvent.ACTION_MOVE) {
// Process the movements starting from the
// earliest historical position in the batch
(0 until event.historySize).forEach { i ->
// Process the event at historical position i
processJoystickInput(event, i)
}
// Process the current movement sample in the batch (position -1)
processJoystickInput(event, -1)
true
} else {
super.onGenericMotionEvent(event)
}
}
}
Java
public class GameView extends View {
@Override
public boolean onGenericMotionEvent(MotionEvent event) {
// Check that the event came from a game controller
if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) ==
InputDevice.SOURCE_JOYSTICK &&
event.getAction() == MotionEvent.ACTION_MOVE) {
// Process all historical movement samples in the batch
final int historySize = event.getHistorySize();
// Process the movements starting from the
// earliest historical position in the batch
for (int i = 0; i < historySize; i++) {
// Process the event at historical position i
processJoystickInput(event, i);
}
// Process the current movement sample in the batch (position -1)
processJoystickInput(event, -1);
return true;
}
return super.onGenericMotionEvent(event);
}
}
Avant d'utiliser l'entrée du joystick, vous devez déterminer si le joystick est centré, puis calculer les mouvements de son axe en conséquence. Les joysticks ont généralement une zone plate, c'est-à-dire une plage de valeurs proche de la coordonnée (0,0) à laquelle l'axe est considéré comme centré. Si la valeur de l'axe signalée par Android se situe dans la zone plate, vous devez considérer que le contrôleur est au repos (c'est-à-dire immobile le long des deux axes).
L'extrait montre une méthode d'assistance qui calcule le mouvement le long de chaque axe. Vous appelez cet utilitaire dans la méthode processJoystickInput() décrite plus loin dans l'exemple suivant :
Kotlin
private fun getCenteredAxis(
event: MotionEvent,
device: InputDevice,
axis: Int,
historyPos: Int
): Float {
val range: InputDevice.MotionRange? = device.getMotionRange(axis, event.source)
// A joystick at rest does not always report an absolute position of
// (0,0). Use the getFlat() method to determine the range of values
// bounding the joystick axis center.
range?.apply {
val value: Float = if (historyPos < 0) {
event.getAxisValue(axis)
} else {
event.getHistoricalAxisValue(axis, historyPos)
}
// Ignore axis values that are within the 'flat' region of the
// joystick axis center.
if (Math.abs(value) > flat) {
return value
}
}
return 0f
}
Java
private static float getCenteredAxis(MotionEvent event,
InputDevice device, int axis, int historyPos) {
final InputDevice.MotionRange range =
device.getMotionRange(axis, event.getSource());
// A joystick at rest does not always report an absolute position of
// (0,0). Use the getFlat() method to determine the range of values
// bounding the joystick axis center.
if (range != null) {
final float flat = range.getFlat();
final float value =
historyPos < 0 ? event.getAxisValue(axis):
event.getHistoricalAxisValue(axis, historyPos);
// Ignore axis values that are within the 'flat' region of the
// joystick axis center.
if (Math.abs(value) > flat) {
return value;
}
}
return 0;
}
En combinant tous ces éléments, voici comment vous pouvez traiter les mouvements du joystick dans votre jeu :
Kotlin
private fun processJoystickInput(event: MotionEvent, historyPos: Int) {
val inputDevice = event.device
// Calculate the horizontal distance to move by
// using the input value from one of these physical controls:
// the left control stick, hat axis, or the right control stick.
var x: Float = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_X, historyPos)
if (x == 0f) {
x = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_HAT_X, historyPos)
}
if (x == 0f) {
x = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_Z, historyPos)
}
// Calculate the vertical distance to move by
// using the input value from one of these physical controls:
// the left control stick, hat switch, or the right control stick.
var y: Float = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_Y, historyPos)
if (y == 0f) {
y = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_HAT_Y, historyPos)
}
if (y == 0f) {
y = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_RZ, historyPos)
}
// Update the ship object based on the new x and y values
}
Java
private void processJoystickInput(MotionEvent event,
int historyPos) {
InputDevice inputDevice = event.getDevice();
// Calculate the horizontal distance to move by
// using the input value from one of these physical controls:
// the left control stick, hat axis, or the right control stick.
float x = getCenteredAxis(event, inputDevice,
MotionEvent.AXIS_X, historyPos);
if (x == 0) {
x = getCenteredAxis(event, inputDevice,
MotionEvent.AXIS_HAT_X, historyPos);
}
if (x == 0) {
x = getCenteredAxis(event, inputDevice,
MotionEvent.AXIS_Z, historyPos);
}
// Calculate the vertical distance to move by
// using the input value from one of these physical controls:
// the left control stick, hat switch, or the right control stick.
float y = getCenteredAxis(event, inputDevice,
MotionEvent.AXIS_Y, historyPos);
if (y == 0) {
y = getCenteredAxis(event, inputDevice,
MotionEvent.AXIS_HAT_Y, historyPos);
}
if (y == 0) {
y = getCenteredAxis(event, inputDevice,
MotionEvent.AXIS_RZ, historyPos);
}
// Update the ship object based on the new x and y values
}
Pour prendre en charge les manettes de jeu dotées de fonctionnalités plus sophistiquées qu'un simple joystick, suivez ces bonnes pratiques :
- Gérer les deux joysticks de la manette. De nombreuses manettes de jeu sont équipées d'un joystick gauche et d'un joystick droit. Pour le joystick gauche, Android signale les mouvements horizontaux comme des événements
AXIS_Xet les mouvements verticaux comme des événementsAXIS_Y. Pour le joystick droit, Android signale les mouvements horizontaux comme des événementsAXIS_Zet les mouvements verticaux comme des événementsAXIS_RZ. Assurez-vous de gérer les deux joysticks de la manette dans votre code. - Gérez les pressions sur les gâchettes (et assurez-vous que votre jeu fonctionne avec les événements
AXIS_etKEYCODE_BUTTON_). Certains contrôleurs sont dotés de boutons de tranche gauche et droite. Lorsque ces déclencheurs sont présents, ils émettent un événementAXIS_*TRIGGERouKEYCODE_BUTTON_*2, ou les deux. Pour le déclencheur gauche, il s'agit deAXIS_LTRIGGERetKEYCODE_BUTTON_L2. Pour le bouton de tranche droit, il s'agit deAXIS_RTRIGGERetKEYCODE_BUTTON_R2. Les événements d'axe ne se produisent que si le déclencheur émet une plage de valeurs comprise entre 0 et 1. Certains contrôleurs avec sortie analogique émettent des événements de bouton en plus des événements d'axe. Les jeux doivent prendre en charge les événementsAXIS_etKEYCODE_BUTTON_pour rester compatibles avec toutes les manettes de jeu courantes. Toutefois, si une manette signale les deux, privilégiez l'événement qui a le plus de sens pour votre gameplay. Sur Android 4.3 (niveau d'API 18) et versions ultérieures, un contrôleur qui produit unAXIS_LTRIGGERsignale également une valeur identique pour l'axeAXIS_BRAKE. Il en va de même pourAXIS_RTRIGGERetAXIS_GAS. Android signale toutes les pressions sur les boutons de déclenchement analogiques avec une valeur normalisée comprise entre 0.0 (relâché) et 1.0 (complètement enfoncé). - Les comportements et l'assistance spécifiques peuvent varier dans les environnements émulés.
Le comportement des plates-formes émulées, telles que Google Play Jeux, peut varier légèrement en fonction des capacités du système d'exploitation hôte. Par exemple, certains contrôleurs qui émettent des événements
AXIS_etKEYCODE_BUTTON_n'émettent que des événementsAXIS_, et la prise en charge de certains contrôleurs peut être totalement manquante.
Variantes courantes
Étant donné la grande variété de manettes compatibles avec Android, il peut être difficile de savoir comment créer et tester votre jeu pour vérifier qu'il fonctionne sans bug pour votre base de joueurs. Nous avons constaté que, malgré cette apparente variété, les fabricants de manettes du monde entier ont tendance à s'en tenir à trois styles de manettes différents. Certains appareils proposent des boutons matériels pour basculer entre deux ou plusieurs de ces modes.
Cela signifie que vous pouvez effectuer des tests avec seulement trois manettes au sein de votre équipe de développement et être sûr que votre jeu est jouable sans avoir recours à des listes d'autorisation et de refus.
Types de contrôleurs courants
Le style de contrôleurs le plus courant tend à imiter la mise en page des consoles de jeu populaires. Cela concerne à la fois l'esthétique des libellés et de la mise en page des boutons, et la fonctionnalité des événements déclenchés. Les manettes avec des boutons matériels permettant de basculer entre différents types de consoles modifient les événements qu'elles envoient et souvent même la disposition logique de leurs boutons.
Lors des tests, nous vous recommandons de vérifier que votre jeu fonctionne avec un contrôleur de chaque catégorie. Vous pouvez choisir de tester avec des contrôleurs propriétaires ou des fabricants tiers populaires. En général, nous mappons les manettes les plus populaires à la définition ci-dessus au mieux de nos capacités.
| Type de contrôleur | Différences de comportement | Variantes de libellés |
|---|---|---|
| Manettes de style Xbox
Il s'agit de manettes généralement conçues pour la plate-forme Microsoft Xbox et Windows*. |
Ces contrôleurs correspondent à l'ensemble de fonctionnalités décrit dans Traiter les entrées du contrôleur. | Les boutons L2/R2 de ces manettes sont appelés LT/RT. |
| Manettes de style Switch
Ces manettes sont généralement conçues pour la famille de consoles Nintendo Switch*. |
Ces contrôleurs envoient les KeyEvent
KEYCODE_BUTTON_R2
KEYCODE_BUTTON_L2
MotionEvent |
Les boutons L2/R2 de ces manettes sont appelés ZL/ZR.
Ces manettes inversent également les boutons A et B, ainsi que les boutons X et Y. Par conséquent, |
| Manettes de style PlayStation
Ces manettes sont généralement conçues pour la famille de consoles Sony PlayStation*. |
Ces manettes envoient des MotionEvent, comme les manettes de style Xbox, mais aussi des KeyEvent, comme les manettes de style Switch, lorsqu'elles sont complètement enfoncées. |
Ces manettes utilisent un ensemble de glyphes différent pour les boutons du dessus. |
* Microsoft, Xbox et Windows sont des marques déposées de Microsoft ; Nintendo Switch est une marque déposée de Nintendo of America Inc.; PlayStation est une marque déposée de Sony Interactive Entertainment Inc.
Désambiguïser les boutons de déclenchement
Certains contrôleurs envoient AXIS_LTRIGGER et AXIS_RTRIGGER, d'autres envoient KEYCODE_BUTTON_L2 et KEYCODE_BUTTON_R2, et d'autres encore envoient tous ces événements en fonction de leurs capacités matérielles. Maximisez la compatibilité en prenant en charge tous ces événements.
Toutes les manettes qui envoient AXIS_LTRIGGER envoient également AXIS_BRAKE, de même pour AXIS_RTRIGGER et AXIS_GAS, afin de maximiser la compatibilité entre les volants de course et les manettes de jeu classiques. En général, cela ne pose pas de problème, mais soyez vigilant pour les fonctionnalités telles que les écrans de remappage des touches.
| Trigger | MotionEvent |
KeyEvent |
|---|---|---|
| Gâchette gauche | AXIS_LTRIGGERAXIS_BRAKE
|
KEYCODE_BUTTON_L2
|
| Gâchette de droite | AXIS_RTRIGGERAXIS_GAS
|
KEYCODE_BUTTON_R2
|
Veillez à vérifier que votre jeu peut gérer à la fois KeyEvent et MotionEvent pour maintenir la compatibilité avec le plus grand nombre de manettes possible et que les événements ne sont pas dupliqués.
Manettes compatibles
Lors des tests, nous vous recommandons de vérifier que votre jeu fonctionne avec un contrôleur de chaque catégorie.
- Style Xbox
- Style Nintendo Switch
- Style PlayStation
Vous pouvez effectuer des tests avec des manettes first party ou des fabricants tiers populaires. Nous mappons généralement les manettes les plus populaires à la définition aussi précisément que possible.