Korzystanie z biblioteki kontrolerów gier

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

Inicjowanie i niszczenie biblioteki Game Controller

Użyj funkcji Paddleboat_init, aby zainicjować bibliotekę Game Controller.

Paddleboat_ErrorCode Paddleboat_init(JNIEnv *env, jobject jcontext)

Paddleboat_init przyjmuje 2 parametry:

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ć Paddleboat_isInitialized, aby sprawdzić, czy biblioteka GameController została prawidłowo zainicjowana. Zwraca wartość logiczną. Jeśli ma wartość Prawda, interfejs API jest dostępny.

bool Paddleboat_isInitialized()

Przed zakończeniem działania aplikacji użyj funkcji Paddleboat_destroy do zamknięcia biblioteki Game Controller. Funkcja przyjmuje jeden parametr, wskaźnik do JNIEnv dołączonego do bieżącego wątku. Paddleboat_init może ponownie zadzwonić po Paddleboat_destroy.

void Paddleboat_destroy(JNIEnv *env)

Informowanie biblioteki o zdarzeniach cyklu życia

Biblioteka Game Controller musi być informowana o cyklu życia aktywności onStoponStart zdarzeniach. Wywołaj funkcje Paddleboat_onStopPaddleboat_onStart w kodzie 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 Game Controller używa wywołania zwrotnego stanu kontrolera, aby powiadamiać grę o podłączeniu lub odłączeniu kontrolera. Obsługuje tylko 1 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ż wartość NULL lub nullptr.
  • Parametr userData jest opcjonalnym wskaźnikiem danych zdefiniowanych przez użytkownika. Parametr userData zostanie przekazany do funkcji wywołania zwrotnego. Ten wskaźnik jest przechowywany wewnętrznie do czasu zmiany przez kolejne wywołanie funkcji Paddleboat_setControllerStatusCallback.
void Paddleboat_setControllerStatusCallback(Paddleboat_ControllerStatusCallback
  statusCallback, void *userData)

Podpis funkcji wywołania zwrotnego jest następujący:

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. 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 w ostatnim wywołaniu funkcji Paddleboat_setControllerStatusCallback.

Wywołanie funkcji aktualizacji biblioteki Game Controller

Funkcję aktualizacji biblioteki Game Controller,Paddleboat_update należy wywoływać 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)

Przetwarzanie zdarzeń

Gdy gra otrzymuje zdarzenia wejściowe, musi przekazywać je do biblioteki Game Controller w celu sprawdzenia. Biblioteka Game Controller sprawdza, 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 Game Controller obsługuje 2 rodzaje zdarzeń wejściowych: AInputEventsGameActivity.

Przetwarzanie AInputEvent

Gra powinna przekazywać wartość AInputEvents, wywołując funkcję Paddleboat_processInputEvent w kodzie obsługi zdarzeń.

int32_t Paddleboat_processInputEvent(const AInputEvent *event)

Paddleboat_processInputEvent zwróci wartość 0, jeśli zdarzenie zostało zignorowane, i 1, jeśli zostało przetworzone i wykorzystane przez bibliotekę Game Controller.

Przetwarzanie zdarzeń GameActivity

Jeśli Twoja gra korzysta z GameActivity, przekazuj zdarzenia GameActivityKeyEventGameActivityMotionEvent, 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 wywoływanej funkcji.
eventSize Rozmiar w bajtach struktury zdarzenia przekazanej w parametrze event.

Obie funkcje zwracają wartość 0, jeśli zdarzenie zostało zignorowane, i 1, jeśli zostało przetworzone i wykorzystane przez bibliotekę Game Controller.

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

uint64_t Paddleboat_getActiveAxisMask()

Przykład obsługi tego problemu znajdziesz w przykładzie biblioteki Game Controller, która korzysta z GameActivity. Przykładowy kod odpytuje maskę aktywnej osi i informuje,GameActivity kiedy 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;
        }
    }
}

Odczytywanie kontrolerów

Biblioteka Game Controller używa wartości indeksu do odwoływania 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 określonego indeksu kontrolera.

Paddleboat_ControllerStatus Paddleboat_getControllerStatus(
  const int32_t controllerIndex)

Istnieją 3 funkcje odczytywania informacji z podłączonego kontrolera.

Nazwa kontrolera

Funkcja Paddleboat_getControllerName function przyjmuje 2 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 użyciem kodowania UTF-8. Nazwa urządzenia jest uzyskiwana wewnętrznie za pomocą funkcji InputDevice.getName().

Jeśli funkcja Paddleboat_getControllerName prawidłowo pobierze nazwę, zwróci wartość 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. Wartość z zakresu od 0 do
.PADDLEBOAT_MAX_CONTROLLERS - 1
bufferSize Rozmiar w bajtach bufora przekazanego przez controllerName. W razie potrzeby 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 będzie przechowywana nazwa kontrolera. Nazwa będzie przechowywana jako ciąg znaków C z kodowaniem UTF-8.

Informacje o urządzeniu sterującym

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

Jeśli funkcja Paddleboat_Controller_Info została wypełniona danymi, Paddleboat_getControllerInfo zwraca PADDLEBOAT_NO_ERROR, w przeciwnym razie zwracany jest 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 pozycji środkowej. Ta wartość jest przydatna głównie do obliczania domyślnej strefy martwej na środku urządzeń samocentrujących.
  • Wartość stickFuzz reprezentuje tolerancję błędu, czyli jak bardzo bieżąca wartość może odbiegać od rzeczywistej wartości z powodu szumu i ograniczeń czułości urządzenia.

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

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

Wykonanie logicznej operacji AND na wartości controllerFlags z wartością PADDLEBOAT_CONTROLLER_LAYOUT_MASK daje w rezultacie wartość, którą można przekształcić w wyliczenie Paddleboat_ControllerButtonLayout. Ten wyliczenie 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
};

Stałe poniżej definiują bity możliwości. Aby sprawdzić, czy kontroler obsługuje daną funkcję, wykonaj logiczną operację AND na odpowiedniej stałej i wartości controllerFlags. Wynik różny od zera oznacza, że kontroler obsługuje tę funkcję.

PADDLEBOAT_CONTROLLER_FLAG_TOUCHPAD

Jeśli ten bit flagi jest ustawiony, kontroler ma zintegrowany touchpad. Jeśli naciśniesz panel dotykowy, kontroler ustawi 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 kontrolera

Funkcja Paddleboat_getControllerData przyjmuje 2 parametry wejściowe: indeks kontrolera i wskaźnik struktury Paddleboat_Controller_Data. Jeśli zmienna Paddleboat_Controller_Data zostanie wypełniona danymi, funkcja Paddleboat_getControllerInfo zwróci wartość PADDLEBOAT_NO_ERROR. W przeciwnym razie zwrócony zostanie odpowiedni kod błędu.

Paddleboat_ErrorCode Paddleboat_getControllerData(const int32_t controllerIndex,
  Paddleboat_Controller_Data *controllerData)

Struktura Paddleboat_Controller_Data zawiera aktualne 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 danych wejściowych Zakres wartości
Oś drążka Od -1.0 do 1.0
Aktywatory Od 0.0 do 1.0
Wskaźniki wirtualne 0.0 do szerokości/wysokości okna (w pikselach)

Szczegóły struktury

Członek struktury Opis
buttonsDown Tablica pól bitowych typu „bit na przycisk”. Stałe maski bitowe przycisków są zdefiniowane w pliku nagłówkowym paddleboat.h i zaczynają się od znaku PADDLEBOAT_BUTTON_.
timestamp. Sygnatura czasowa ostatniego zdarzenia wejścia kontrolera. Sygnatura czasowa jest wyrażona w mikrosekundach od początku epoki zegara.
virtualPointer Lokalizacja wskaźnika wirtualnego. Obowiązuje tylko wtedy, gdy w parametrze controllerFlags ustawiona jest flaga PADDLEBOAT_CONTROLLER_FLAG_VIRTUAL_MOUSE. W przeciwnym razie będzie to 0.0, 0.0.