Utiliser la bibliothèque Game Controller

Les fonctions suivantes vous permettent d'ajouter la prise en charge des manettes à votre jeu à l'aide de la bibliothèque Game Controller.

Initialiser et détruire la bibliothèque Game Controller

Utilisez la fonction Paddleboat_init pour initialiser la bibliothèque Game Controller.

Paddleboat_ErrorCode Paddleboat_init(JNIEnv *env, jobject jcontext)

Paddleboat_init comporte deux paramètres :

  • Un pointeur vers un objet JNIEnv associé au thread actuel
  • Une référence d'objet JNI jobject à une classe dérivée de Context. Tout objet de classe dérivé de Context est valide, y compris, mais sans s'y limiter Activity, NativeActivity ou GameActivity.

Paddleboat_init renvoie PADDLEBOAT_NO_ERROR si l'initialisation a réussi. Sinon, le code d'erreur approprié est renvoyé.

Vous pouvez utiliser la fonction Paddleboat_isInitialized pour vérifier si la bibliothèque Game Controller a bien été initialisée. Elle renvoie une valeur booléenne. Si la valeur est "true", l'API est disponible.

bool Paddleboat_isInitialized()

Avant d'arrêter l'application, utilisez la fonction Paddleboat_destroy pour arrêter la bibliothèque Game Controller. La fonction accepte un seul paramètre, un pointeur vers un objet JNIEnv associé au thread actuel. Paddleboat_init peut être rappelé après Paddleboat_destroy.

void Paddleboat_destroy(JNIEnv *env)

Informer la bibliothèque des événements de cycle de vie

La bibliothèque Game Controller doit être informée des événements onStop et onStart du cycle de vie de l'activité Appelez les fonctions Paddleboat_onStop et Paddleboat_onStart à partir de votre code de gestion des événements de lancement et d'arrêt. Les deux fonctions n'utilisent qu'un seul paramètre : un pointeur vers un objet JNIEnv associé au thread actuel.

void Paddleboat_onStop(JNIEnv *env)
void Paddleboat_onStart(JNIEnv *env)

Enregistrer ou supprimer un rappel d'état de la manette

La bibliothèque Game Controller utilise un rappel d'état de la manette pour avertir un jeu de la connexion ou de la déconnexion d'une manette. Elle n'accepte qu'un seul rappel d'état de la manette à la fois.

  • Pour enregistrer un rappel d'état de la manette ou remplacer un rappel précédemment enregistré par une nouvelle fonction de rappel, appelez la fonction Paddleboat_setControllerStatusCallback.
  • Pour supprimer un rappel actuellement enregistré, transmettez NULL ou nullptr.
  • Le paramètre userData est un pointeur facultatif vers des données définies par l'utilisateur. Le paramètre userData sera transmis à la fonction de rappel. Ce pointeur est conservé en interne jusqu'à ce qu'il soit modifié par un appel ultérieur à Paddleboat_setControllerStatusCallback.
void Paddleboat_setControllerStatusCallback(Paddleboat_ControllerStatusCallback
  statusCallback, void *userData)

La signature de la fonction de rappel est la suivante :

typedef void (*Paddleboat_ControllerStatusCallback)(
  const int32_t controllerIndex,
  const Paddleboat_ControllerStatus controllerStatus,
  void *userData)
Paramètre Description
controllerIndex Index de la manette qui a initié le rappel. Valeur comprise entre 0 et
PADDLEBOAT_MAX_CONTROLLERS - 1
controllerStatus Valeur d'énumération de PADDLEBOAT_CONTROLLER_JUST_CONNECTED ou
PADDLEBOAT_CONTROLLER_JUST_DISCONNECTED.
userData Pointeur facultatif (peut être NULL) vers les données définies par l'utilisateur spécifiées par le dernier appel à Paddleboat_setControllerStatusCallback.

Appeler la fonction de mise à jour de la bibliothèque Game Controller

La fonction de mise à jour de la bibliothèque Game Controller, Paddleboat_update, doit être appelée une fois par frame de jeu, de préférence vers le début du frame. La fonction utilise un seul paramètre, un pointeur vers un objet JNIEnv associé au thread actuel.

void Paddleboat_update(JNIEnv *env)

Traiter les événements

Lorsqu'il reçoit des événements d'entrée, votre jeu doit les transférer vers la bibliothèque Game Controller pour inspection. La bibliothèque Game Controller évalue si un événement d'entrée est associé à l'un des appareils qu'elle gère. Les événements provenant d'appareils gérés sont traités et consommés.

La bibliothèque Game Controller accepte deux types d'événements d'entrée : AInputEvents et GameActivity.

Traitement des événements AInputEvent

Votre jeu doit transférer AInputEvents en appelant Paddleboat_processInputEvent depuis votre code de gestion des événements.

int32_t Paddleboat_processInputEvent(const AInputEvent *event)

Paddleboat_processInputEvent renvoie 0 si l'événement a été ignoré et 1 si l'événement a été traité et consommé par la bibliothèque Game Controller.

Traitement des événements GameActivity

Si votre jeu utilise GameActivity, transférez les événements GameActivityKeyEvent et GameActivityMotionEvent en appelant Paddleboat_processGameActivityKeyInputEvent ou Paddleboat_processGameActivityMotionInputEvent depuis votre code de gestion des événements.

int32_t Paddleboat_processGameActivityKeyInputEvent(const void *event,
                                                    const size_t eventSize)
int32_t Paddleboat_processGameActivityMotionInputEvent(const void *event,
                                                       const size_t eventSize)
Paramètre Description
event Un pointeur vers une structure GameActivityKeyEvent ou GameActivityMotionEvent, selon la fonction appelée.
eventSize La taille en octets de la structure d'événement transmise au paramètre event.

Les deux fonctions renvoient 0 si l'événement a été ignoré et 1 si l'événement a été traité et consommé par la bibliothèque Game Controller.

GameActivity nécessite de spécifier l'axe de mouvement actif à l'aide de la fonction GameActivityPointerAxes_enableAxis. L'appel de la fonction Paddleboat_getActiveAxisMask renvoie le masque de bits de l'axe de mouvement actuellement utilisé par les manettes connectées.

uint64_t Paddleboat_getActiveAxisMask()

Pour savoir comment procéder, consultez l'exemple de bibliothèque Game Controller qui utilise GameActivity. L'exemple interroge le masque de l'axe actif et informe GameActivity lors de l'utilisation d'un nouvel axe. Cette opération est implémentée dans la fonction NativeEngine::CheckForNewAxis().

void NativeEngine::CheckForNewAxis() {
    // Tell GameActivity about any new axis ids so it reports
    // their events
    const uint64_t activeAxisIds = Paddleboat_getActiveAxisMask();
    uint64_t newAxisIds = activeAxisIds ^ mActiveAxisIds;
    if (newAxisIds != 0) {
        mActiveAxisIds = activeAxisIds;
        int32_t currentAxisId = 0;
        while(newAxisIds != 0) {
            if ((newAxisIds & 1) != 0) {
                LOGD("Enable Axis: %d", currentAxisId);
                GameActivityPointerAxes_enableAxis(currentAxisId);
            }
            ++currentAxisId;
            newAxisIds >>= 1;
        }
    }
}

Lire des manettes

La bibliothèque Game Controller utilise une valeur d'index pour faire référence à une manette spécifique. Les valeurs d'index valides sont comprises entre 0 et PADDLEBOAT_MAX_CONTROLLERS - 1. La fonction Paddleboat_getControllerStatus détermine l'état d'un index de manette spécifié.

Paddleboat_ControllerStatus Paddleboat_getControllerStatus(
  const int32_t controllerIndex)

Trois fonctions permettent de lire les informations d'une manette connectée.

Nom de la manette

La fonction Paddleboat_getControllerName function accepte deux paramètres d'entrée : un index de manette, une taille de mémoire tampon et un pointeur vers un tampon pour stocker la chaîne de nom de la manette. La chaîne de nom est mise en forme en tant que chaîne C à l'aide de l'encodage UTF-8. Le nom du périphérique est obtenu en interne à l'aide de InputDevice.getName().

Si Paddleboat_getControllerName parvient à récupérer le nom, il renvoie PADDLEBOAT_NO_ERROR, sinon le code d'erreur approprié est renvoyé.

Paddleboat_ErrorCode Paddleboat_getControllerName(const int32_t controllerIndex,
                                                  const size_t bufferSize,
                                                  char *controllerName);
Paramètre Description
controllerIndex Index de la manette qui a initié le rappel. Valeur comprise entre 0 et
PADDLEBOAT_MAX_CONTROLLERS - 1
bufferSize Taille en octets du tampon transmise par controllerName. La chaîne de nom sera tronquée si nécessaire pour tenir dans le tampon.
controllerName Pointeur vers un tampon de bufferSize octets dans lequel stocker le nom de la manette. Le nom sera stocké sous forme de chaîne C à l'aide de l'encodage UTF-8.

Informations concernant la manette

La fonction Paddleboat_getControllerInfo function accepte deux paramètres d'entrée : un index de manette et un pointeur vers une structure Paddleboat_Controller_Info.

Si Paddleboat_Controller_Info a correctement été renseigné avec des données, Paddleboat_getControllerInfo renvoie PADDLEBOAT_NO_ERROR. Sinon, le code d'erreur approprié est renvoyé.

Paddleboat_ErrorCode Paddleboat_getControllerInfo(const int32_t controllerIndex,
  Paddleboat_Controller_Info *controllerInfo)

La structure Paddleboat_Controller_Info contient des informations propres à l'appareil concernant la manette.

typedef struct Paddleboat_Controller_Info {
    uint32_t controllerFlags;
    int32_t controllerNumber;
    int32_t vendorId;
    int32_t productId;
    int32_t deviceId;
    Paddleboat_Controller_Thumbstick_Precision leftStickPrecision;
    Paddleboat_Controller_Thumbstick_Precision rightStickPrecision;
} Paddleboat_Controller_Info;

typedef struct Paddleboat_Controller_Thumbstick_Precision {
    float stickFlatX;
    float stickFlatY;
    float stickFuzzX;
    float stickFuzzY;
} Paddleboat_Controller_Thumbstick_Precision;

Plusieurs membres de structure sont renseignés à partir des valeurs provenant du InputDevice associé à la manette :

controllerNumber    -   InputDevice.getControllerNumber()
vendorId              - InputDevice.getVendorId()
productId             - InputDevice.getProductId()
deviceId              - InputDevice.getId()
  • Une valeur stickFlat représente l'étendue d'une position centrale. Cette valeur est principalement utile pour calculer une "zone morte" par défaut sur les appareils avec centrage automatique.
  • Une valeur stickFuzz représente la tolérance à l'erreur, c'est-à-dire dans quelle mesure la valeur actuelle peut s'écarter de la valeur réelle en raison des limitations liées au bruit et à la sensibilité de l'appareil.

Les deux valeurs sont normalisées à une valeur maximale d'axe de 1.0 dans les deux dimensions.

Le membre controllerFlags contient une combinaison d'indicateurs individuels sous forme de masques de bits et de valeurs de combinaison sur plusieurs bits.

L'exécution d'une valeur logique AND de controllerFlags avec PADDLEBOAT_CONTROLLER_LAYOUT_MASK génère une valeur pouvant être castée dans l'énumération Paddleboat_ControllerButtonLayout. Cette énumération spécifie l'icône et la disposition du bouton utilisées par la manette.

enum Paddleboat_ControllerButtonLayout {
    //  Y
    // X B
    //  A
    PADDLEBOAT_CONTROLLER_LAYOUT_STANDARD = 0,
    //  △
    // □ ○
    //  x
    PADDLEBOAT_CONTROLLER_LAYOUT_SHAPES = 1,
    //  X
    // Y A
    //  B
    PADDLEBOAT_CONTROLLER_LAYOUT_REVERSE = 2,
    // X Y R1 L1
    // A B R2 L2
    PADDLEBOAT_CONTROLLER_LAYOUT_ARCADE_STICK = 3,
    PADDLEBOAT_CONTROLLER_LAYOUT_MASK = 3
};

Les constantes suivantes définissent les bits de capacité. Pour déterminer si une manette accepte une capacité particulière, exécutez une requête logique AND de la constante par rapport aux controllerFlags. Un résultat différent de zéro signifie que la capacité est prise en charge par la manette.

PADDLEBOAT_CONTROLLER_FLAG_TOUCHPAD

Si ce bit d'indicateur est défini, la manette dispose d'un pavé tactile intégré. Si vous appuyez sur le pavé tactile, le contrôleur définit le bit PADDLEBOAT_BUTTON_TOUCHPAD dans le champ Paddleboat_Controller_Data.buttonsDown.

PADDLEBOAT_CONTROLLER_FLAG_VIRTUAL_MOUSE

Si ce bit d'indicateur est défini, la manette émule un dispositif de pointage. Le membre virtualPointer de la structure Paddleboat_Controller_Data contient les coordonnées actuelles du pointeur virtuel.

Données de la manette

La fonction Paddleboat_getControllerData accepte deux paramètres d'entrée : un index de manette et un pointeur vers une structure Paddleboat_Controller_Data. Si Paddleboat_Controller_Data est correctement renseigné avec des données, Paddleboat_getControllerInfo renvoie PADDLEBOAT_NO_ERROR. Sinon, le code d'erreur approprié est renvoyé.

Paddleboat_ErrorCode Paddleboat_getControllerData(const int32_t controllerIndex,
  Paddleboat_Controller_Data *controllerData)

La structure Paddleboat_Controller_Data contient les valeurs d'entrée de contrôle actuelles de la manette.

typedef struct Paddleboat_Controller_Data {
    uint64_t timestamp;
    uint32_t buttonsDown;
    Paddleboat_Controller_Thumbstick leftStick;
    Paddleboat_Controller_Thumbstick rightStick;
    float triggerL1;
    float triggerL2;
    float triggerR1;
    float triggerR2;
    Paddleboat_Controller_Pointer virtualPointer;
} Paddleboat_Controller_Data;

typedef struct Paddleboat_Controller_Pointer {
    float pointerX;
    float pointerY;
} Paddleboat_Controller_Pointer;

typedef struct Paddleboat_Controller_Thumbstick {
    float stickX;
    float stickY;
} Paddleboat_Controller_Thumbstick;

Plages de valeurs

Type d'entrée Plage de valeurs
Axe du joystick De -1.0 à 1.0
Gâchettes De 0.0 à 1.0
Pointeurs virtuels De 0.0 à la largeur/hauteur de la fenêtre (en pixels)

Détails de la structure

Membre de la structure Description
buttonsDown Tableau des champs de bits par bouton. Les constantes de masque de bits de bouton sont définies dans le fichier d'en-tête paddleboat.h et commencent par PADDLEBOAT_BUTTON_.
timestamp. Code temporel du dernier événement d'entrée de la manette. Le code temporel est exprimé en microsecondes depuis l'epoch de l'horloge.
virtualPointer Emplacement du pointeur virtuel. N'est valide que si l'indicateur PADDLEBOAT_CONTROLLER_FLAG_VIRTUAL_MOUSE est défini sur controllerFlags. Sinon, la valeur sera 0.0, 0.0.