Gamecontroller-Bibliothek verwenden

Mit den folgenden Funktionen können Sie Ihrem Spiel mithilfe der Game Controller-Bibliothek Unterstützung für Gamecontroller hinzufügen.

Game Controller-Bibliothek initialisieren und löschen

Verwenden Sie die Funktion Paddleboat_init, um die Game Controller-Bibliothek zu initialisieren.

Paddleboat_ErrorCode Paddleboat_init(JNIEnv *env, jobject jcontext)

Paddleboat_init verwendet zwei Parameter:

  • Ein Verweis auf ein JNIEnv, das mit dem aktuellen Thread verknüpft ist
  • Ein jobject-JNI-Objektverweis auf eine abgeleitete Context-Klasse. Jedes abgeleitete Context-Klassenobjekt ist gültig, einschließlich, aber nicht beschränkt auf Activity, NativeActivity oder GameActivity.

Paddleboat_init gibt PADDLEBOAT_NO_ERROR zurück, wenn die Initialisierung erfolgreich war. Andernfalls wird ein entsprechender Fehlercode zurückgegeben.

Mit Paddleboat_isInitialized kannst du prüfen, ob die Game Controller-Bibliothek erfolgreich initialisiert wurde. Sie gibt einen booleschen Wert zurück. Wenn „true“ festgelegt ist, kann die API verwendet werden.

bool Paddleboat_isInitialized()

Verwenden Sie vor dem Beenden der Anwendung die Funktion Paddleboat_destroy, um die Game Controller-Bibliothek herunterzufahren. Die Funktion verwendet einen einzelnen Parameter, einen Zeiger auf einen JNIEnv, der an den aktuellen Thread angehängt ist. Paddleboat_init kann nach dem Paddleboat_destroy noch einmal aufgerufen werden.

void Paddleboat_destroy(JNIEnv *env)

Bibliothek über Lebenszyklusereignisse informieren

Die Game Controller-Bibliothek muss über den Aktivitätslebenszyklus onStop und über onStart-Ereignisse informiert werden. Rufen Sie im Verarbeitungscode für Stopp- und Start-Ereignisse die Funktionen Paddleboat_onStop und Paddleboat_onStart auf. Beide Funktionen verwenden einen einzelnen Parameter: einen Zeiger auf eine JNIEnv, die an den aktuellen Thread angehängt ist.

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

Controller-Status-Callback registrieren oder entfernen

Die Game Controller-Bibliothek verwendet einen Controller-Status-Callback, um ein Spiel darüber zu informieren, wenn ein Controller verbunden oder getrennt wird. Es unterstützt jeweils nur einen Controllerstatus-Callback.

  • Wenn Sie einen Controller-Status-Callback registrieren oder einen zuvor registrierten Callback durch eine neue Callback-Funktion ersetzen möchten, rufen Sie die Paddleboat_setControllerStatusCallback-Funktion auf.
  • Übergeben Sie NULL oder nullptr, um einen derzeit registrierten Callback zu entfernen.
  • Der Parameter userData ist ein optionaler Zeiger auf benutzerdefinierte Daten. Der Parameter userData wird an die Callback-Funktion übergeben. Dieser Zeiger wird intern beibehalten, bis er durch einen nachfolgenden Aufruf von Paddleboat_setControllerStatusCallback geändert wird.
void Paddleboat_setControllerStatusCallback(Paddleboat_ControllerStatusCallback
  statusCallback, void *userData)

Die Funktionssignatur der Callback-Funktion lautet:

typedef void (*Paddleboat_ControllerStatusCallback)(
  const int32_t controllerIndex,
  const Paddleboat_ControllerStatus controllerStatus,
  void *userData)
Parameter Beschreibung
controllerIndex Index des Controllers, der den Callback initiiert hat. Ist ein Wert zwischen 0 und
. PADDLEBOAT_MAX_CONTROLLERS - 1
controllerStatus Enum-Wert von PADDLEBOAT_CONTROLLER_JUST_CONNECTED oder
PADDLEBOAT_CONTROLLER_JUST_DISCONNECTED.
userData Ein optionaler Zeiger (kann NULL sein) auf benutzerdefinierte Daten, die durch den letzten Aufruf von Paddleboat_setControllerStatusCallback angegeben wurden.

Updatefunktion der Gamecontroller-Mediathek aufrufen

Die Aktualisierungsfunktion Paddleboat_update der Gamecontroller-Mediathek sollte einmal pro Spiel-Frame aufgerufen werden, vorzugsweise am Anfang des Frames. Die Funktion verwendet einen einzelnen Parameter, einen Zeiger auf einen JNIEnv, der an den aktuellen Thread angehängt ist.

void Paddleboat_update(JNIEnv *env)

Ereignisse verarbeiten

Wenn Ihr Spiel Eingabeereignisse erhält, muss es sie zur Prüfung an die Game Controller-Bibliothek weiterleiten. Die Game Controller-Bibliothek wertet aus, ob einem ihrer verwalteten Geräte ein Eingabeereignis zugeordnet ist. Ereignisse von verwalteten Geräten werden verarbeitet und konsumiert.

Die Game Controller-Bibliothek unterstützt zwei Arten von Eingabeereignissen: AInputEvents- und GameActivity-Eingabeereignisse.

AInputEvent-Verarbeitung

Ihr Spiel sollte AInputEvents weiterleiten, indem Paddleboat_processInputEvent über Ihren Ereignisverarbeitungscode aufgerufen wird.

int32_t Paddleboat_processInputEvent(const AInputEvent *event)

Paddleboat_processInputEvent gibt 0 zurück, wenn das Ereignis ignoriert wurde, und 1, wenn es von der Game Controller-Bibliothek verarbeitet und genutzt wurde.

GameActivity-Ereignis wird verarbeitet

Wenn Ihr Spiel GameActivity verwendet, leiten Sie Ereignisse vom Typ GameActivityKeyEvent und GameActivityMotionEvent weiter, indem Sie Paddleboat_processGameActivityKeyInputEvent oder Paddleboat_processGameActivityMotionInputEvent über Ihren Ereignisverarbeitungscode aufrufen.

int32_t Paddleboat_processGameActivityKeyInputEvent(const void *event,
                                                    const size_t eventSize)
int32_t Paddleboat_processGameActivityMotionInputEvent(const void *event,
                                                       const size_t eventSize)
Parameter Beschreibung
event Ein Zeiger auf eine GameActivityKeyEvent- oder GameActivityMotionEvent-Struktur, je nachdem, welche Funktion aufgerufen wird.
eventSize Die Größe der im Parameter event übergebenen Ereignisstruktur in Byte.

Beide Funktionen geben 0 zurück, wenn das Ereignis ignoriert wurde, und 1, wenn das Ereignis von der Game Controller-Bibliothek verarbeitet und genutzt wurde.

Für GameActivity muss die aktive Bewegungsachse mit der Funktion GameActivityPointerAxes_enableAxis angegeben werden. Der Aufruf Paddleboat_getActiveAxisMask gibt eine Bitmaske der derzeit aktiven Bewegungsachse zurück, die von verbundenen Controllern verwendet wird.

uint64_t Paddleboat_getActiveAxisMask()

Ein Beispiel dafür findest du im Beispiel der Game Controller-Bibliothek, in dem GameActivity verwendet wird. Das Beispiel fragt die aktive Achsenmaske ab und informiert GameActivity, wenn eine neue Achse verwendet wird. Dies wird in der Funktion NativeEngine::CheckForNewAxis() implementiert.

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

Controller lesen

Die Game Controller-Bibliothek verwendet einen Indexwert, um auf einen bestimmten Controller zu verweisen. Gültige Indexwerte reichen von 0 bis PADDLEBOAT_MAX_CONTROLLERS - 1. Die Funktion Paddleboat_getControllerStatus bestimmt den Status eines angegebenen Controller-Index.

Paddleboat_ControllerStatus Paddleboat_getControllerStatus(
  const int32_t controllerIndex)

Es gibt drei Funktionen zum Lesen von Informationen von einem verbundenen Controller.

Name des Controllers

Paddleboat_getControllerName function verwendet zwei Eingabeparameter: einen Controller-Index, eine Puffergröße und einen Verweis auf einen Zwischenspeicher zum Speichern des Controller-Namens. Der Namensstring wird als C-String mit UTF-8-Codierung formatiert. Der Name des Geräts wird intern mit InputDevice.getName() abgerufen.

Wenn Paddleboat_getControllerName den Namen erfolgreich abruft, wird PADDLEBOAT_NO_ERROR zurückgegeben. Andernfalls wird ein entsprechender Fehlercode zurückgegeben.

Paddleboat_ErrorCode Paddleboat_getControllerName(const int32_t controllerIndex,
                                                  const size_t bufferSize,
                                                  char *controllerName);
Parameter Beschreibung
controllerIndex Index des Controllers, der den Callback initiiert hat. Ist ein Wert zwischen 0 und
. PADDLEBOAT_MAX_CONTROLLERS - 1
bufferSize Größe in Byte des von controllerName übergebenen Zwischenspeichers. Der Namensstring wird dabei bei Bedarf abgeschnitten, um in den Zwischenspeicher zu passen.
controllerName Ein Verweis auf einen Zwischenspeicher von bufferSize Byte, in dem der Controllername gespeichert wird. Der Name wird als C-String mit UTF-8-Codierung gespeichert.

Geräteinformationen zum Controller

Der Paddleboat_getControllerInfo function verwendet zwei Eingabeparameter: einen Controller-Index und einen Zeiger auf eine Paddleboat_Controller_Info-Struktur.

Wenn Paddleboat_Controller_Info erfolgreich mit Daten gefüllt wurde, gibt Paddleboat_getControllerInfo den Wert PADDLEBOAT_NO_ERROR zurück. Andernfalls wird ein entsprechender Fehlercode zurückgegeben.

Paddleboat_ErrorCode Paddleboat_getControllerInfo(const int32_t controllerIndex,
  Paddleboat_Controller_Info *controllerInfo)

Die Paddleboat_Controller_Info-Struktur enthält gerätespezifische Informationen zum 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;

Mehrere Strukturmitglieder werden mit Werten gefüllt, die aus dem InputDevice stammen, das dem Controller zugeordnet ist:

controllerNumber    -   InputDevice.getControllerNumber()
vendorId              - InputDevice.getVendorId()
productId             - InputDevice.getProductId()
deviceId              - InputDevice.getId()
  • Ein stickFlat-Wert gibt die Ausdehnung einer flachen Mitte an. Dieser Wert ist hauptsächlich nützlich, um auf selbstzentrierten Geräten eine standardmäßige zentralisierte „Tote Zone“ zu berechnen.
  • Ein stickFuzz-Wert steht für die Fehlertoleranz oder gibt an, wie weit der aktuelle Wert aufgrund von Rauschen- und Geräteempfindlichkeitsbeschränkungen vom tatsächlichen Wert abweichen kann.

Beide Werte werden in beiden Dimensionen auf den maximalen Achsenwert 1.0 normalisiert.

Das Mitglied controllerFlags enthält eine Kombination aus einzelnen Bitmasken-Flags und Mehr-Bit-Kombinationswerten.

Die Ausführung eines logischen AND von controllerFlags mit PADDLEBOAT_CONTROLLER_LAYOUT_MASK führt zu einem Wert, der in die Aufzählung Paddleboat_ControllerButtonLayout umgewandelt werden kann. Diese Enum gibt die Symbole und das Layout der Schaltfläche an, die vom Controller verwendet werden.

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

Die folgenden Konstanten definieren Funktionsbits. Um festzustellen, ob ein Controller eine bestimmte Funktion unterstützt, führst du einen logischen AND der entsprechenden Konstante in Bezug auf controllerFlags aus. Ein Ergebnis ungleich null bedeutet, dass die Funktion vom Controller unterstützt wird.

PADDLEBOAT_CONTROLLER_FLAG_TOUCHPAD

Wird dieses Flag gesetzt, verfügt der Controller über ein integriertes Touchpad. Wenn das Touchpad gedrückt wird, setzt der Controller das PADDLEBOAT_BUTTON_TOUCHPAD-Bit im Feld Paddleboat_Controller_Data.buttonsDown.

PADDLEBOAT_CONTROLLER_FLAG_VIRTUAL_MOUSE

Wenn dieses Flag-Bit gesetzt ist, emuliert der Controller ein Zeigergerät. Das virtualPointer-Mitglied der Paddleboat_Controller_Data-Struktur enthält die aktuellen Koordinaten des virtuellen Zeigers.

Daten des Verantwortlichen

Die Funktion Paddleboat_getControllerData verwendet zwei Eingabeparameter: einen Controller-Index und einen Zeiger auf eine Paddleboat_Controller_Data-Struktur. Wenn Paddleboat_Controller_Data erfolgreich mit Daten gefüllt wurde, gibt Paddleboat_getControllerInfo den Wert PADDLEBOAT_NO_ERROR zurück. Andernfalls wird ein entsprechender Fehlercode zurückgegeben.

Paddleboat_ErrorCode Paddleboat_getControllerData(const int32_t controllerIndex,
  Paddleboat_Controller_Data *controllerData)

Die Paddleboat_Controller_Data-Struktur enthält die aktuellen Steuereingabewerte des Controllers.

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;

Wertebereiche

Eingabetyp Wertebereich
Thumbstick-Achse -1.0 bis 1.0
Trigger 0.0 bis 1.0
Virtuelle Hinweise 0.0 bis Fensterbreite/-höhe (in Pixeln)

Gebäudedetails

Gebäudemitglied Beschreibung
buttonsDown Bitfeld-Array pro Schaltfläche. Die Bitmaskenkonstanten für die Schaltfläche werden in der Header-Datei paddleboat.h definiert und beginnen mit PADDLEBOAT_BUTTON_.
timestamp. Zeitstempel des letzten Controller-Eingabeereignisses. Der Zeitstempel wird in Mikrosekunden seit der Epoche angegeben.
virtualPointer Position des virtuellen Zeigers. Nur gültig, wenn das Flag PADDLEBOAT_CONTROLLER_FLAG_VIRTUAL_MOUSE in controllerFlags festgelegt ist. Andernfalls ist 0.0, 0.0 der Wert.