Korzystanie z biblioteki kontrolerów gier

Aby dodać do gry obsługę kontrolera za pomocą biblioteki kontrolera do gier, użyj tych funkcji.

Inicjowanie i niszczenie biblioteki kontrolera do gier

Użyj funkcji Paddleboat_init, aby zainicjować bibliotekę kontrolera do gier.

Paddleboat_ErrorCode Paddleboat_init(JNIEnv *env, jobject jcontext)

Paddleboat_init przyjmuje 2 parametry:

  • Wskaźnik do obiektu JNIEnv dołączonego do bieżącego wątku.
  • Odwołanie do obiektu JNI jobject do klasy pochodnej Context. Każdy obiekt klasy pochodnej Context jest prawidłowy, w tym między innymi Activity, NativeActivity i GameActivity.

Paddleboat_init zwraca PADDLEBOAT_NO_ERROR, jeśli inicjowanie się powiodło. W przeciwnym razie zwracany jest odpowiedni kod błędu.

Możesz użyć funkcji Paddleboat_isInitialized, aby sprawdzić, czy biblioteka kontrolera do gier została pomyślnie zainicjowana. Zwraca wartość logiczną. Jeśli ma wartość Prawda, interfejs API jest dostępny do użycia.

bool Paddleboat_isInitialized()

Przed zakończeniem działania aplikacji użyj funkcji Paddleboat_destroy, aby wyłączyć bibliotekę kontrolera do gier. Funkcja przyjmuje jeden parametr, wskaźnik do obiektu JNIEnv dołączonego do bieżącego wątku. Funkcję Paddleboat_init można wywołać ponownie po Paddleboat_destroy.

void Paddleboat_destroy(JNIEnv *env)

Informowanie biblioteki o zdarzeniach cyklu życia

Biblioteka kontrolera do gier musi być informowana o zdarzeniach cyklu życia działania onStop i onStart. Wywołaj funkcje Paddleboat_onStop i Paddleboat_onStart z kodu obsługi zdarzeń zatrzymania i rozpoczęcia. Obie funkcje przyjmują jeden parametr: wskaźnik do obiektu JNIEnv dołączonego do bieżącego wątku.

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

Rejestrowanie lub usuwanie wywołania zwrotnego stanu kontrolera

Biblioteka kontrolera do gier używa wywołania zwrotnego stanu kontrolera, aby powiadomić grę o podłączeniu lub odłączeniu kontrolera. Obsługuje tylko jedno wywołanie zwrotne stanu kontrolera naraz.

  • Aby zarejestrować wywołanie zwrotne stanu kontrolera lub zastąpić wcześniej zarejestrowane wywołanie zwrotne nową funkcją wywołania zwrotnego, wywołaj funkcję Paddleboat_setControllerStatusCallback.
  • Aby usunąć zarejestrowane wywołanie zwrotne, przekaż NULL lub nullptr.
  • Parametr userData to opcjonalny wskaźnik do danych zdefiniowanych przez użytkownika. Do funkcji wywołania zwrotnego zostanie przekazany parametr userData. Ten wskaźnik jest przechowywany wewnętrznie do momentu, gdy zostanie zmieniony przez kolejne wywołanie funkcji Paddleboat_setControllerStatusCallback.
void Paddleboat_setControllerStatusCallback(Paddleboat_ControllerStatusCallback
  statusCallback, void *userData)

Podpis funkcji wywołania zwrotnego:

typedef void (*Paddleboat_ControllerStatusCallback)(
  const int32_t controllerIndex,
  const Paddleboat_ControllerStatus controllerStatus,
  void *userData)
Parametr Opis
controllerIndex Indeks kontrolera, który zainicjował wywołanie zwrotne. Będzie to wartość z zakresu od 0 do 
. PADDLEBOAT_MAX_CONTROLLERS - 1
controllerStatus Wartość typu wyliczeniowego PADDLEBOAT_CONTROLLER_JUST_CONNECTED lub
PADDLEBOAT_CONTROLLER_JUST_DISCONNECTED.
userData Opcjonalny wskaźnik (może mieć wartość NULL) do danych zdefiniowanych przez użytkownika, określonych przez ostatnie wywołanie funkcji Paddleboat_setControllerStatusCallback.

Wywoływanie funkcji aktualizacji biblioteki kontrolera do gier

Funkcja aktualizacji biblioteki kontrolera do gier, Paddleboat_update, powinna być wywoływana raz na klatkę gry, najlepiej na początku klatki. Funkcja przyjmuje jeden parametr, wskaźnik do JNIEnv dołączonego do bieżącego wątku.

void Paddleboat_update(JNIEnv *env)

Zdarzenia procesów

Po otrzymaniu zdarzeń wejściowych gra musi przekazać je do biblioteki kontrolera do gier w celu sprawdzenia. Biblioteka kontrolera do gier ocenia, czy zdarzenie wejściowe jest powiązane z jednym z zarządzanych urządzeń. Zdarzenia z urządzeń zarządzanych są przetwarzane i wykorzystywane.

Biblioteka kontrolera do gier obsługuje 2 typy zdarzeń wejściowych: AInputEvents i GameActivity.

Przetwarzanie zdarzeń AInputEvent

Gra powinna przekazywać AInputEvents, wywołując Paddleboat_processInputEvent z kodu obsługi zdarzeń.

int32_t Paddleboat_processInputEvent(const AInputEvent *event)

Paddleboat_processInputEvent zwróci 0, jeśli zdarzenie zostało zignorowane, i 1, jeśli zdarzenie zostało przetworzone i wykorzystane przez bibliotekę kontrolera do gier.

Przetwarzanie zdarzeń GameActivity

Jeśli Twoja gra korzysta z GameActivity, przekazuj zdarzenia GameActivityKeyEvent i GameActivityMotionEvent, wywołując Paddleboat_processGameActivityKeyInputEvent lub Paddleboat_processGameActivityMotionInputEvent z kodu obsługi zdarzeń.

int32_t Paddleboat_processGameActivityKeyInputEvent(const void *event,
                                                    const size_t eventSize)
int32_t Paddleboat_processGameActivityMotionInputEvent(const void *event,
                                                       const size_t eventSize)
Parametr Opis
event Wskaźnik do struktury GameActivityKeyEvent lub GameActivityMotionEvent, w zależności od tego, która funkcja jest wywoływana.
eventSize Rozmiar w bajtach struktury zdarzenia przekazanej w parametrze event.

Obie funkcje zwrócą wartość 0, jeśli zdarzenie zostało zignorowane, i 1, jeśli zdarzenie zostało przetworzone i wykorzystane przez bibliotekę kontrolera do gier.

GameActivity wymaga określenia aktywnej osi ruchu za pomocą funkcji GameActivityPointerAxes_enableAxis. Wywołanie Paddleboat_getActiveAxisMask zwraca maskę bitową aktualnie aktywnych osi ruchu używanych przez połączone kontrolery.

uint64_t Paddleboat_getActiveAxisMask()

Przykład obsługi tego zdarzenia znajdziesz w przykładzie biblioteki kontrolera do gier, który używa GameActivity. Próbka sprawdza aktywną maskę osi i informuje GameActivity, gdy używane są nowe osie. Jest to zaimplementowane w funkcji 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;
        }
    }
}

Odczyt kontrolerów

Biblioteka kontrolera do gier używa wartości indeksu, aby odwoływać się do konkretnego kontrolera. Prawidłowe wartości indeksu mieszczą się w zakresie od 0 do PADDLEBOAT_MAX_CONTROLLERS - 1. Funkcja Paddleboat_getControllerStatus określa stan podanego indeksu kontrolera.

Paddleboat_ControllerStatus Paddleboat_getControllerStatus(
  const int32_t controllerIndex)

Dostępne są 3 funkcje odczytywania informacji z połączonego kontrolera.

Nazwa kontrolera

Funkcja Paddleboat_getControllerName przyjmuje 3 parametry wejściowe: indeks kontrolera, rozmiar bufora i wskaźnik do bufora, w którym ma być przechowywany ciąg znaków z nazwą kontrolera. Ciąg znaków nazwy jest sformatowany jako ciąg znaków C z kodowaniem UTF-8. Nazwa urządzenia jest uzyskiwana wewnętrznie za pomocą InputDevice.getName().

Jeśli Paddleboat_getControllerName pomyślnie pobierze nazwę, zwróci PADDLEBOAT_NO_ERROR. W przeciwnym razie zwróci odpowiedni kod błędu.

Paddleboat_ErrorCode Paddleboat_getControllerName(const int32_t controllerIndex,
                                                  const size_t bufferSize,
                                                  char *controllerName);
Parametr Opis
controllerIndex Indeks kontrolera, który zainicjował wywołanie zwrotne. Będzie to wartość z zakresu od 0 do 
. PADDLEBOAT_MAX_CONTROLLERS - 1
bufferSize Rozmiar w bajtach bufora przekazanego przez controllerName. Jeśli to konieczne, ciąg nazwy zostanie obcięty, aby zmieścił się w buforze.
controllerName Wskaźnik do bufora o rozmiarze bufferSize bajtów, w którym ma być przechowywana nazwa kontrolera. Nazwa zostanie zapisana jako ciąg znaków C z kodowaniem UTF-8.

Informacje o urządzeniu kontrolera

Funkcja Paddleboat_getControllerInfo przyjmuje 2 parametry wejściowe: indeks kontrolera i wskaźnik do struktury Paddleboat_Controller_Info.

Jeśli Paddleboat_Controller_Info zostanie pomyślnie wypełniony danymi, Paddleboat_getControllerInfo zwróci PADDLEBOAT_NO_ERROR. W przeciwnym razie zostanie zwrócony odpowiedni kod błędu.

Paddleboat_ErrorCode Paddleboat_getControllerInfo(const int32_t controllerIndex,
  Paddleboat_Controller_Info *controllerInfo)

Struktura Paddleboat_Controller_Info zawiera informacje o kontrolerze dotyczące konkretnego urządzenia.

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;

Kilka elementów struktury jest wypełnianych wartościami pobranymi z InputDevice powiązanego z kontrolerem:

controllerNumber    -   InputDevice.getControllerNumber()
vendorId              - InputDevice.getVendorId()
productId             - InputDevice.getProductId()
deviceId              - InputDevice.getId()
  • Wartość stickFlat reprezentuje zakres środkowej płaskiej pozycji. Ta wartość jest przydatna głównie do obliczania domyślnej „martwej strefy” w środku na urządzeniach samocentrujących.
  • Wartość stickFuzz reprezentuje tolerancję błędu, czyli to, jak bardzo bieżąca wartość może odbiegać od rzeczywistej z powodu zakłóceń i ograniczeń czułości urządzenia.

Obie wartości są normalizowane do maksymalnej wartości osi wynoszącej 1.0 w każdym wymiarze.

Element controllerFlags zawiera kombinację pojedynczych flag z maską bitową i wartości kombinacji wielobitowych.

Wykonanie logicznego AND na controllerFlags z PADDLEBOAT_CONTROLLER_LAYOUT_MASK daje wartość, którą można rzutować na typ wyliczeniowy Paddleboat_ControllerButtonLayout. Ten typ wyliczeniowy określa ikonografię i układ przycisków używane przez kontroler.

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

Poniższe stałe definiują bity funkcji. Aby sprawdzić, czy kontroler obsługuje daną funkcję, wykonaj logiczne AND odpowiedniej stałej względem controllerFlags. Wynik inny niż zero oznacza, że kontroler obsługuje tę funkcję.

PADDLEBOAT_CONTROLLER_FLAG_TOUCHPAD

Jeśli ten bit flagi jest ustawiony, kontroler ma zintegrowany touchpad. Jeśli touchpad jest naciśnięty, kontroler ustawia bit PADDLEBOAT_BUTTON_TOUCHPAD w polu Paddleboat_Controller_Data.buttonsDown.

PADDLEBOAT_CONTROLLER_FLAG_VIRTUAL_MOUSE

Jeśli ten bit flagi jest ustawiony, kontroler emuluje urządzenie wskazujące. Element virtualPointer struktury Paddleboat_Controller_Data jest wypełniany bieżącymi współrzędnymi wskaźnika wirtualnego.

Dane administratora

Funkcja Paddleboat_getControllerData przyjmuje 2 parametry wejściowe: indeks kontrolera i wskaźnik do struktury Paddleboat_Controller_Data. Jeśli Paddleboat_Controller_Data zostanie pomyślnie wypełniony danymi, Paddleboat_getControllerData zwróci PADDLEBOAT_NO_ERROR. W przeciwnym razie zostanie zwrócony odpowiedni kod błędu.

Paddleboat_ErrorCode Paddleboat_getControllerData(const int32_t controllerIndex,
  Paddleboat_Controller_Data *controllerData)

Struktura Paddleboat_Controller_Data zawiera bieżące wartości wejściowe kontrolera.

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;

Zakresy wartości

Typ kolumny wejściowej Zakres wartości
Oś gałki analogowej Od -1.0 do 1.0
Aktywatory Od 0.0 do 1.0
Wirtualne wskaźniki 0.0 do szerokości/wysokości okna (w pikselach)

Szczegóły struktury

Domownik Opis
buttonsDown Tablica pól bitowych z bitami na przycisk. Stałe maski bitowej przycisku są zdefiniowane w pliku nagłówka paddleboat.h i zaczynają się od PADDLEBOAT_BUTTON_.
timestamp Sygnatura czasowa ostatniego zdarzenia wejściowego kontrolera. Sygnatura czasowa to mikrosekundy od początku epoki zegara.
virtualPointer Lokalizacja wirtualnego wskaźnika. Jest prawidłowa tylko wtedy, gdy flaga PADDLEBOAT_CONTROLLER_FLAG_VIRTUAL_MOUSE jest ustawiona w controllerFlags. W przeciwnym razie będzie to 0.0, 0.0.