Utilizzare la raccolta del controller di gioco

Utilizza le seguenti funzioni per aggiungere il supporto del controller di gioco al tuo gioco utilizzando la libreria Game Controller.

Inizializzare e distruggere la libreria Game Controller

Utilizza la funzione Paddleboat_init per inizializzare la libreria Game Controller.

Paddleboat_ErrorCode Paddleboat_init(JNIEnv *env, jobject jcontext)

Paddleboat_init accetta due parametri:

  • Un puntatore a un JNIEnv allegato al thread corrente
  • Un riferimento a un oggetto JNI jobject a una classe derivata Context. Qualsiasi oggetto della classe derivata Context è valido, inclusi, a titolo esemplificativo, Activity, NativeActivity o GameActivity.

Paddleboat_init restituisce PADDLEBOAT_NO_ERROR se l'inizializzazione è riuscita, altrimenti viene restituito un codice di errore appropriato.

Puoi utilizzare Paddleboat_isInitialized per verificare se la libreria Game Controller è stata inizializzata correttamente. Restituisce un valore booleano. Se è true, l'API è disponibile per l'uso.

bool Paddleboat_isInitialized()

Prima di terminare l'applicazione, utilizza la funzione Paddleboat_destroy per arrestare la libreria Game Controller. La funzione accetta un singolo parametro, un puntatore a un JNIEnv collegato al thread corrente. Paddleboat_init potrebbe essere richiamato dopo il giorno Paddleboat_destroy.

void Paddleboat_destroy(JNIEnv *env)

Informare la libreria degli eventi del ciclo di vita

La libreria Game Controller deve essere informata del ciclo di vita dell'attività onStop e degli onStart eventi. Chiama le funzioni Paddleboat_onStop e Paddleboat_onStart dal codice di gestione degli eventi di arresto e avvio. Entrambe le funzioni richiedono un unico parametro: un puntatore a un JNIEnv collegato al thread corrente.

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

Registrare o rimuovere un callback dello stato del controller

La libreria Game Controller utilizza un callback dello stato del controller per notificare a un gioco quando un controller è connesso o disconnesso. Supporta una sola callback di stato del controller alla volta.

  • Per registrare un callback di stato del controller o sostituire qualsiasi callback registrato in precedenza con una nuova funzione di callback, chiama la funzione Paddleboat_setControllerStatusCallback.
  • Per rimuovere qualsiasi callback attualmente registrato, passa NULL o nullptr.
  • Il parametro userData è un puntatore facoltativo ai dati definiti dall'utente. Il parametro userData verrà passato alla funzione di callback. Questo puntatore viene conservato internamente finché non viene modificato da una chiamata successiva a Paddleboat_setControllerStatusCallback.
void Paddleboat_setControllerStatusCallback(Paddleboat_ControllerStatusCallback
  statusCallback, void *userData)

La firma della funzione di callback è:

typedef void (*Paddleboat_ControllerStatusCallback)(
  const int32_t controllerIndex,
  const Paddleboat_ControllerStatus controllerStatus,
  void *userData)
Parametro Descrizione
controllerIndex Indice del controller che ha avviato il callback. Sarà un valore compreso tra 0 e
PADDLEBOAT_MAX_CONTROLLERS - 1
controllerStatus Valore enum di PADDLEBOAT_CONTROLLER_JUST_CONNECTED o
PADDLEBOAT_CONTROLLER_JUST_DISCONNECTED.
userData Un puntatore facoltativo (può essere NULL) ai dati definiti dall'utente specificati dall'ultima chiamata a Paddleboat_setControllerStatusCallback.

Chiamare la funzione di aggiornamento della libreria Game Controller

La funzione di aggiornamento della libreria Game Controller, Paddleboat_update , deve essere chiamata una volta per frame di gioco, preferibilmente all'inizio del frame. La funzione accetta un singolo parametro, un puntatore a un JNIEnv collegato al thread corrente.

void Paddleboat_update(JNIEnv *env)

Elaborare eventi

Quando riceve eventi di input, il gioco deve inoltrarli alla libreria Game Controller per l'ispezione. La libreria Game Controller valuta se un evento di input è associato a uno dei dispositivi gestiti. Gli eventi provenienti dai dispositivi gestiti vengono elaborati e utilizzati.

La libreria Game Controller supporta due tipi di eventi di input: AInputEvents e GameActivity.

Elaborazione di AInputEvent

Il gioco deve inoltrare AInputEvents chiamando Paddleboat_processInputEvent dal codice di gestione degli eventi.

int32_t Paddleboat_processInputEvent(const AInputEvent *event)

Paddleboat_processInputEvent restituirà 0 se l'evento è stato ignorato e 1 se l'evento è stato elaborato e utilizzato dalla libreria Game Controller.

Elaborazione eventi GameActivity

Se il tuo gioco utilizza GameActivity, inoltra gli eventi GameActivityKeyEvent e GameActivityMotionEvent chiamando Paddleboat_processGameActivityKeyInputEvent o Paddleboat_processGameActivityMotionInputEvent dal codice di gestione degli eventi.

int32_t Paddleboat_processGameActivityKeyInputEvent(const void *event,
                                                    const size_t eventSize)
int32_t Paddleboat_processGameActivityMotionInputEvent(const void *event,
                                                       const size_t eventSize)
Parametro Descrizione
event Un puntatore a una struttura GameActivityKeyEvent o GameActivityMotionEvent, a seconda della funzione chiamata.
eventSize Le dimensioni in byte della struttura dell'evento trasmessa nel parametro event.

Entrambe le funzioni restituiranno 0 se l'evento è stato ignorato e 1 se l'evento è stato elaborato e utilizzato dalla libreria Game Controller.

GameActivity richiede che l'asse di movimento attivo venga specificato utilizzando la funzione GameActivityPointerAxes_enableAxis. La chiamata Paddleboat_getActiveAxisMask restituisce una maschera di bit dell'asse di movimento attualmente attivo utilizzato dai controller connessi.

uint64_t Paddleboat_getActiveAxisMask()

Per un esempio di come gestire questo problema, consulta l'esempio della libreria Game Controller che utilizza GameActivity. Il campione esegue il polling della maschera dell'asse attivo e informa GameActivity quando vengono utilizzati nuovi assi. Questa operazione viene implementata nella funzione 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;
        }
    }
}

Lettura controller

La libreria Game Controller utilizza un valore di indice per fare riferimento a un controller specifico. I valori di indice validi sono compresi tra 0 e PADDLEBOAT_MAX_CONTROLLERS - 1. La funzione Paddleboat_getControllerStatus determina lo stato di un indice del controller specificato.

Paddleboat_ControllerStatus Paddleboat_getControllerStatus(
  const int32_t controllerIndex)

Esistono tre funzioni per leggere le informazioni da un controller connesso.

Nome del controller

La funzione Paddleboat_getControllerName function accetta due parametri di input: un indice del controller, una dimensione del buffer e un puntatore a un buffer per memorizzare la stringa del nome del controller. La stringa del nome è formattata come una stringa C utilizzando la codifica UTF-8. Il nome del dispositivo viene ottenuto internamente utilizzando InputDevice.getName().

Se Paddleboat_getControllerName recupera correttamente il nome, restituisce PADDLEBOAT_NO_ERROR, altrimenti viene restituito un codice di errore appropriato.

Paddleboat_ErrorCode Paddleboat_getControllerName(const int32_t controllerIndex,
                                                  const size_t bufferSize,
                                                  char *controllerName);
Parametro Descrizione
controllerIndex Indice del controller che ha avviato il callback. Sarà un valore compreso tra 0 e
PADDLEBOAT_MAX_CONTROLLERS - 1
bufferSize Dimensione in byte del buffer passato da controllerName, la stringa del nome verrà troncata se necessario per adattarsi al buffer.
controllerName Un puntatore a un buffer di bufferSize byte per memorizzare il nome del controller. Il nome verrà memorizzato come stringa C utilizzando la codifica UTF-8.

Informazioni sul dispositivo controller

Paddleboat_getControllerInfo function accetta due parametri di input: un indice del controller e un puntatore a una struttura Paddleboat_Controller_Info.

Se Paddleboat_Controller_Info è stato compilato correttamente con i dati, Paddleboat_getControllerInfo restituisce PADDLEBOAT_NO_ERROR, altrimenti viene restituito un codice di errore appropriato.

Paddleboat_ErrorCode Paddleboat_getControllerInfo(const int32_t controllerIndex,
  Paddleboat_Controller_Info *controllerInfo)

La struttura Paddleboat_Controller_Info contiene informazioni specifiche del dispositivo sul controller.

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;

Diversi membri della struttura vengono compilati con valori presi dal InputDevice associato al controller:

controllerNumber    -   InputDevice.getControllerNumber()
vendorId              - InputDevice.getVendorId()
productId             - InputDevice.getProductId()
deviceId              - InputDevice.getId()
  • Un valore stickFlat rappresenta l'estensione di una posizione centrale piatta. Questo valore è utile principalmente per calcolare una "zona morta" centrale predefinita sui dispositivi autocentranti.
  • Un valore stickFuzz rappresenta la tolleranza all'errore o la distanza che il valore attuale può discostarsi dal valore effettivo a causa di limitazioni di rumore e sensibilità del dispositivo.

Entrambi i valori sono normalizzati a un valore massimo dell'asse di 1.0 in entrambe le dimensioni.

Il membro controllerFlags contiene una combinazione di flag con maschera di bit individuali e valori di combinazione di più bit.

L'esecuzione di un'operazione logica AND di controllerFlags con PADDLEBOAT_CONTROLLER_LAYOUT_MASK restituisce un valore che può essere convertito nell'enumerazione Paddleboat_ControllerButtonLayout. Questo enum specifica l'iconografia e il layout dei pulsanti utilizzati dal controller.

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

Le seguenti costanti definiscono i bit di funzionalità. Per determinare se un controller supporta una funzionalità specifica, esegui un'operazione logica AND della costante corrispondente rispetto a controllerFlags. Un risultato diverso da zero indica che la funzionalità è supportata dal controller.

PADDLEBOAT_CONTROLLER_FLAG_TOUCHPAD

Se questo bit di flag è impostato, il controller ha un touchpad integrato. Se il touchpad viene premuto, il controller imposta il bit PADDLEBOAT_BUTTON_TOUCHPAD nel campo Paddleboat_Controller_Data.buttonsDown.

PADDLEBOAT_CONTROLLER_FLAG_VIRTUAL_MOUSE

Se questo bit di flag è impostato, il controller emula un dispositivo di puntamento. Il membro virtualPointer della struttura Paddleboat_Controller_Data è compilato con le coordinate attuali del puntatore virtuale.

Dati del controller

La funzione Paddleboat_getControllerData accetta due parametri di input: un indice del controller e un puntatore a una struttura Paddleboat_Controller_Data. Se Paddleboat_Controller_Data viene compilato correttamente con i dati, Paddleboat_getControllerInfo restituisce PADDLEBOAT_NO_ERROR, altrimenti viene restituito un codice di errore appropriato.

Paddleboat_ErrorCode Paddleboat_getControllerData(const int32_t controllerIndex,
  Paddleboat_Controller_Data *controllerData)

La struttura Paddleboat_Controller_Data contiene i valori di input di controllo attuali del controller.

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;

Intervalli di valori

Tipo di input Intervallo di valori
Asse della levetta Da -1.0 a 1.0
Attivatori Da 0.0 a 1.0
Puntatori virtuali Da 0.0 alla larghezza/altezza della finestra (in pixel)

Dettagli della struttura

Membro della struttura Descrizione
buttonsDown Array di campi di bit per pulsante. Le costanti della maschera di bit dei pulsanti sono definite nel file di intestazione paddleboat.h e iniziano con PADDLEBOAT_BUTTON_.
timestamp. Timestamp dell'evento di input del controller più recente. Il timestamp è in microsecondi dall'epoca dell'orologio.
virtualPointer Posizione del puntatore virtuale. Valido solo se il flag PADDLEBOAT_CONTROLLER_FLAG_VIRTUAL_MOUSE è impostato in controllerFlags, altrimenti sarà 0.0, 0.0.