Les manettes comportent deux types d'actions :
KeyEventutilisé pour tout bouton avec un état binaire "activé" et "désactivé"MotionEventutilisé 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 la View qui a le focus.
onGenericMotionEventest déclenché pour toutMotionEvent.onKeyDownetonKeyUpsont déclenchés pourKeyEventlorsque les boutons sont enfoncés et relâchés.
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 directement les événements à partir de Activity.
dispatchGenericMotionEventest déclenché pour toutMotionEventdispatchKeyEvent. est déclenché pour toutKeyEvent.
Vérifier qu'une manette de jeu est connectée
Lors du signalement 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
AXIS_X événement qui représente la coordonnée X
de la surface tactile, mais une manette de jeu génère un
AXIS_X événement qui représente la position X
du joystick 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
supportsSource(int) fonction :
- Un type de source
SOURCE_GAMEPADindique que le périphérique d'entrée comporte des boutons de manette (par exemple,KEYCODE_BUTTON_A). Notez que ce type de source n'indique pas strictement 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 de pavé directionnel (par exemple,DPAD_UP). - Un type de source
SOURCE_JOYSTICKindique que le périphérique d'entrée comporte des joysticks analogiques (par exemple, un joystick qui enregistre les mouvements le long deAXIS_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 c'est le cas, la méthode récupère les ID d'appareil pour les 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 la section Prise en charge de 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 de la manette
Cette section décrit les types de manettes de jeu compatibles avec Android.
Les développeurs C++ doivent utiliser la bibliothèque Game Controller. Elle unifie toutes les manettes dans le sous-ensemble de fonctionnalités le plus courant et fournit une interface cohérente entre elles, 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 répertorie les noms et types d'événements standards pour les manettes de jeu. Pour obtenir la liste complète des événements, consultez la section Variantes courantes. Le système
envoie des événements MotionEvent via onGenericMotionEvent et des événements KeyEvent
via onKeyDown et onKeyUp.
| Entrée de la manette | Événement de touches | 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. Joystick 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 pressions sur les boutons de la manette de la même manière que les pressions sur les boutons du clavier, vous devez procéder comme suit :
- 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 touches répétées 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 le haut et 1,0 indiquant le bas. Il signale les pressions sur les boutons GAUCHE ou DROITE du pavé directionnel comme des événements AXIS_HAT_X, avec -1,0 indiquant la gauche et 1,0 indiquant la droite.
Certaines manettes signalent plutôt les pressions sur le pavé directionnel avec un code de touche. Si votre jeu se soucie des pressions sur le pavé directionnel, vous devez traiter les événements d'axe de 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 touche du pavé directionnel et les valeurs d'axe de chapeau.
| Action de jeu | Code de touche du pavé directionnel | Code d'axe de chapeau |
|---|---|---|
| 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 vers la gauche | KEYCODE_DPAD_LEFT |
AXIS_HAT_X (pour les valeurs comprises entre 0 et -1,0) |
| Déplacer vers la 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 d'axe de chapeau et de code de touche à partir 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
onGenericMotionEvent()
ou
onKeyDown()
rappels).
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 leur manette de jeu, Android signale un
MotionEvent qui contient le
ACTION_MOVE code
d'action 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 exemples de mouvement dans un seul objet. L'
MotionEvent objet contient la
position actuelle de chaque axe du joystick, ainsi que plusieurs positions historiques
pour chaque axe. Lors du signalement des événements de mouvement avec le code d'action
ACTION_MOVE (par exemple,
les mouvements du joystick), Android regroupe les valeurs d'axe pour plus d'efficacité. Les valeurs historiques d'un axe sont constituées de l'ensemble des valeurs distinctes antérieures à la valeur d'axe actuelle et plus récentes que les valeurs signalées dans les événements de mouvement précédents. Pour en savoir plus, consultez la MotionEvent
référence.
Pour afficher avec précision le mouvement d'un objet de jeu en fonction de l'entrée 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
onGenericMotionEvent()
rappel pour traiter l'entrée 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 ses mouvements d'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 d'axe signalée par Android se situe dans la zone plate, vous devez considérer que la manette est au repos (c'est-à-dire immobile sur les deux axes).
L'extrait montre une méthode d'assistance qui calcule le mouvement le long de chaque axe. Vous appelez cette assistance 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;
}
Pour résumer, voici comment 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 seul joystick, suivez ces bonnes pratiques :
- Gérez les deux joysticks de la manette. De nombreuses manettes de jeu comportent un joystick gauche et un joystick droit. Pour le joystick gauche, Android signale les mouvements horizontaux
comme des
AXIS_Xévénements et les mouvements verticaux commeAXIS_Yévénements. Pour le joystick droit, Android signale les mouvements horizontaux comme desAXIS_Zévénements et les mouvements verticaux comme desAXIS_RZévénements. Assurez-vous de gérer les deux joysticks de la manette dans votre code. - Gérez les pressions sur les gâchettes d'épaule (et assurez-vous que votre jeu fonctionne avec les événements
AXIS_etKEYCODE_BUTTON_). Certaines manettes comportent des gâchettes gauche et droite. Lorsque ces gâchettes sont présentes, elles émettent un événementAXIS_*TRIGGERouKEYCODE_BUTTON_*2, ou les deux. Pour la gâchette gauche, il s'agit deAXIS_LTRIGGERetKEYCODE_BUTTON_L2. Pour la gâchette droite, il s'agit deAXIS_RTRIGGERetKEYCODE_BUTTON_R2. Les événements d'axe ne se produisent que si la gâchette émet une plage de valeurs comprise entre 0 et 1, et certaines manettes 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, mais privilégiez l'événement le plus pertinent pour votre gameplay si une manette signale les deux. Sur Android 4.3 (niveau d'API 18) ou version ultérieure, une manette 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 gâchettes analogiques avec une valeur normalisée comprise entre 0,0 (relâchée) et 1,0 (complètement enfoncée). - Les comportements et la compatibilité spécifiques peuvent différer dans les environnements émulés.
Les plates-formes émulées, telles que Google Play Games, peuvent légèrement différer en termes de comportement en fonction des fonctionnalités du système d'exploitation hôte. Par exemple, certaines manettes qui émettent à la fois des événements
AXIS_etKEYCODE_BUTTON_n'émettent que des événementsAXIS_, et la compatibilité avec certaines manettes peut être totalement absente.
Variantes courantes
Compte tenu de la grande variété de manettes compatibles avec Android, il peut être difficile de créer et de tester votre jeu pour vérifier qu'il fonctionne sans bug pour votre base de joueurs. Nous constatons que, malgré cette variété apparente, les fabricants de manettes du monde entier ont tendance à respecter trois styles de manettes différents. Certains proposent des commutateurs matériels entre deux ou plusieurs de ces styles.
Cela signifie que vous pouvez tester votre jeu avec seulement trois manettes au sein de votre équipe de développement et être sûr qu'il est jouable sans avoir recours à des listes d'autorisation et de refus.
Types de manettes courants
Le style de manettes le plus courant a tendance à imiter la disposition des consoles de jeu populaires. Cela est à la fois esthétique dans les libellés et la disposition des boutons, et fonctionnel par les événements déclenchés. Les manettes avec commutateurs matériels entre différents types de consoles modifient les événements qu'elles envoient et souvent même leur disposition logique des boutons.
Lors des tests, nous vous recommandons de vérifier que votre jeu fonctionne avec une manette dans chacune des catégories. Vous pouvez choisir de tester avec des manettes propriétaires ou des fabricants tiers populaires. En général, nous mappons les manettes les plus populaires sur la définition ci-dessus au mieux de nos capacités.
| Type de manette | Différences de comportement | Variations de libellés |
|---|---|---|
| Manettes de style Xbox
Il s'agit généralement de manettes conçues pour la plate-forme Microsoft Xbox et Windows* |
Ces manettes correspondent à l'ensemble de caractéristiques décrit dans la section Traiter les entrées de la manette. | Les boutons L2/R2 de ces manettes sont libellés LT/RT. |
| Manettes de style Switch
Ces manettes sont généralement conçues pour la famille de consoles Nintendo Switch* |
Ces manettes envoient les KeyEvent
KEYCODE_BUTTON_R2
KEYCODE_BUTTON_L2
MotionEvents. |
Les boutons L2/R2 de ces manettes sont libellés ZL/ZR.
Ces manettes inversent également les boutons A et B ainsi que les
boutons X et Y. Ainsi, |
| Manettes de style PlayStation
Ces manettes sont généralement conçues pour la famille de consoles Sony PlayStation* . |
Ces manettes envoient des MotionEvents
comme les manettes de style Xbox, mais aussi des KeyEvents
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 de la face avant. |
* 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.
Distinguer les boutons de déclenchement
Certaines manettes 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. Optimisez la compatibilité en prenant en charge tous ces événements.
Toutes les manettes qui envoient AXIS_LTRIGGER envoient également AXIS_BRAKE, de même que AXIS_RTRIGGER et AXIS_GAS, afin d'optimiser 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 attentif aux fonctionnalités telles que les écrans de remappage des touches.
| Déclencheur | MotionEvent |
KeyEvent |
|---|---|---|
| Gâchette gauche | AXIS_LTRIGGERAXIS_BRAKE
|
KEYCODE_BUTTON_L2
|
| Gâchette droite | AXIS_RTRIGGERAXIS_GAS
|
KEYCODE_BUTTON_R2
|
Vous devez veiller à ce que votre jeu puisse gérer à la fois KeyEvent et MotionEvent pour maintenir la compatibilité avec le plus grand nombre de manettes possible et que les événements soient dédupliqués.
Manettes compatibles
Lors des tests, nous vous recommandons de vérifier que votre jeu fonctionne avec une manette dans chacune des catégories.
- Style Xbox
- Style Nintendo Switch
- Style PlayStation
Vous pouvez tester avec des manettes propriétaires ou des fabricants tiers populaires. En général, nous mappons les manettes les plus populaires sur la définition aussi précisément que possible.