使用遊戲控制器程式庫

您可以使用下列函式,透過遊戲控制器程式庫將遊戲控制器支援加入遊戲。

初始化並刪除遊戲控制器程式庫

使用 Paddleboat_init 函式初始化遊戲控制器程式庫。

Paddleboat_ErrorCode Paddleboat_init(JNIEnv *env, jobject jcontext)

Paddleboat_init 會使用兩個參數:

如果初始化成功,Paddleboat_init 會傳回 PADDLEBOAT_NO_ERROR,否則會傳回適當的錯誤代碼。

您可以使用 Paddleboat_isInitialized 檢查遊戲控制器程式庫是否已成功初始化。它會傳回布林值。如為 true,則可使用 API。

bool Paddleboat_isInitialized()

終止應用程式之前,請先使用 Paddleboat_destroy 函式關閉遊戲控制器程式庫。函式會使用單一參數,並指向目前執行緒附加的 JNIEnv 指標。Paddleboat_init 可能會在 Paddleboat_destroy 後再次呼叫。

void Paddleboat_destroy(JNIEnv *env)

通知生命週期事件資料庫

遊戲控制器程式庫必須隨時掌握活動生命週期onStoponStart 事件。在您的停止位置呼叫 Paddleboat_onStopPaddleboat_onStart 函式,然後啟動事件處理程式碼。兩個函式都使用單一參數:指向目前執行緒附加的 JNIEnv 的指標。

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

註冊或移除控制器狀態回呼

遊戲控制器程式庫會在控制器連線或中斷連線時,使用控制器狀態回呼通知遊戲。一次僅支援一個控制器狀態回呼。

  • 如要註冊控制器狀態回呼,或以新的回呼函式取代任何先前註冊的回呼,請呼叫 Paddleboat_setControllerStatusCallback 函式。
  • 如要移除目前註冊的回呼,請傳遞 NULLnullptr
  • userData 參數是使用者定義資料的選用指標。userData 參數會傳遞到回呼函式。這個指標會在內部保留,直到後續呼叫 Paddleboat_setControllerStatusCallback 為止。
void Paddleboat_setControllerStatusCallback(Paddleboat_ControllerStatusCallback
  statusCallback, void *userData)

回呼函式的函式簽名如下:

typedef void (*Paddleboat_ControllerStatusCallback)(
  const int32_t controllerIndex,
  const Paddleboat_ControllerStatus controllerStatus,
  void *userData)
參數 說明
controllerIndex 啟動回呼的控制器索引。這個值必須介於 0
PADDLEBOAT_MAX_CONTROLLERS - 1 之間
controllerStatus PADDLEBOAT_CONTROLLER_JUST_CONNECTED
PADDLEBOAT_CONTROLLER_JUST_DISCONNECTED 的列舉值。
userData 選用指標 (可能為 NULL),指向上次呼叫 Paddleboat_setControllerStatusCallback 的使用者定義資料。

呼叫遊戲控制器程式庫更新函式

遊戲控制器程式庫的更新函式 Paddleboat_update 應在每個遊戲影格中呼叫一次,最好在接近影格開頭處。這個函式會使用單一參數,指向目前執行緒附加的 JNIEnv 指標。

void Paddleboat_update(JNIEnv *env)

處理事件

收到輸入事件時,您的遊戲必須將輸入事件轉送至遊戲控制器程式庫進行檢查。遊戲控制器程式庫會評估輸入事件是否與其管理的任何裝置相關聯。系統會處理受管理裝置的事件,並消耗這類事件。

遊戲控制器程式庫支援兩種輸入事件:AInputEventsGameActivity 輸入事件。

AInputEvent 處理

您的遊戲應透過事件控制代碼呼叫 Paddleboat_processInputEvent,以轉送 AInputEvents

int32_t Paddleboat_processInputEvent(const AInputEvent *event)

如果事件遭到忽略,Paddleboat_processInputEvent 會傳回 0;如果遊戲控制器程式庫已處理及使用該事件,則會傳回 1

GameActivity 事件處理

如果遊戲使用 GameActivity,請轉寄 GameActivityKeyEvent和 呼叫 GameActivityMotionEvent 事件 Paddleboat_processGameActivityKeyInputEventPaddleboat_processGameActivityMotionInputEvent 使用事件處理程式碼呼叫

int32_t Paddleboat_processGameActivityKeyInputEvent(const void *event,
                                                    const size_t eventSize)
int32_t Paddleboat_processGameActivityMotionInputEvent(const void *event,
                                                       const size_t eventSize)
參數 說明
event 指向 GameActivityKeyEventGameActivityMotionEvent 結構的指標,視呼叫的函式而定。
eventSize 透過 event 參數傳遞的事件結構大小 (以位元組為單位)。

如果事件遭到忽略,則兩個函式都會傳回 0;如果遊戲控制器程式庫已處理及使用該事件,則會傳回 1

GameActivity 要求使用 GameActivityPointerAxes_enableAxis 函式指定使用中的動作軸。而 Paddleboat_getActiveAxisMask 呼叫會傳回已連結控制器目前使用中的動作軸的位元遮罩。

uint64_t Paddleboat_getActiveAxisMask()

如需如何處理此問題的相關範例,請參閱使用 GameActivity 的遊戲控制器程式庫範例。該範例會輪詢使用中的軸遮罩,並在使用新軸時通知 GameActivity。這可透過 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;
        }
    }
}

讀取控制器

遊戲控制器程式庫會使用索引值參照特定控制器。有效索引值的範圍從 0PADDLEBOAT_MAX_CONTROLLERS - 1Paddleboat_getControllerStatus敬上 函式會決定指定控制器索引的狀態。

Paddleboat_ControllerStatus Paddleboat_getControllerStatus(
  const int32_t controllerIndex)

您可透過三個函式讀取已連結控制器的資訊。

控制器名稱

Paddleboat_getControllerName function 會接受兩個輸入參數:控制器索引、緩衝區大小,以及用來儲存控制器名稱字串的緩衝區指標。名稱字串的格式為 C 字串,使用 UTF-8 編碼。使用 InputDevice.getName() 會在內部取得裝置名稱。

如果 Paddleboat_getControllerName 成功擷取名稱,則會傳回 PADDLEBOAT_NO_ERROR,否則會傳回適當的錯誤代碼。

Paddleboat_ErrorCode Paddleboat_getControllerName(const int32_t controllerIndex,
                                                  const size_t bufferSize,
                                                  char *controllerName);
參數 說明
controllerIndex 啟動回呼的控制器索引。這個值必須介於 0
PADDLEBOAT_MAX_CONTROLLERS - 1 之間
bufferSize controllerName 傳送的緩衝區大小 (以位元組為單位),如果需要,名稱字串將被截斷以適合緩衝區大小。
controllerName 指向 bufferSize 位元組緩衝區的指標,用於儲存控制器名稱。系統會將名稱儲存為 C 字串,並使用 UTF-8 編碼。

控制器裝置資訊

Paddleboat_getControllerInfo function 會接受兩個輸入參數:控制器索引和指向 Paddleboat_Controller_Info 結構的指標。

如果 Paddleboat_Controller_Info 已順利填入資料,Paddleboat_getControllerInfo 會傳回 PADDLEBOAT_NO_ERROR,否則會傳回適當的錯誤代碼。

Paddleboat_ErrorCode Paddleboat_getControllerInfo(const int32_t controllerIndex,
  Paddleboat_Controller_Info *controllerInfo)

Paddleboat_Controller_Info 結構包含與該控制器相關的裝置專屬資訊。

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;

一些結構成員會填入從控制器關聯 InputDevice 中擷取的值:

controllerNumber    -   InputDevice.getControllerNumber()
vendorId              - InputDevice.getVendorId()
productId             - InputDevice.getProductId()
deviceId              - InputDevice.getId()
  • stickFlat 值代表中心平坦位置的範圍。這個值主要用於計算自攜式裝置的預設中心「死區」。
  • stickFuzz 值代表錯誤容許值,或是目前值可能會因噪音和裝置敏感度限製而與實際值差距的程度。

兩個值都會按照任一維度正規化為最大軸值 1.0

controllerFlags 成員包含個別位元遮罩旗標和多位元組合值的組合。

使用 PADDLEBOAT_CONTROLLER_LAYOUT_MASK 執行 controllerFlags 的邏輯 AND,會產生一個可投放至 Paddleboat_ControllerButtonLayout 列舉的值。這個列舉值會指定控制器使用的按鈕圖形和版面配置。

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

下列常數可定義功能位元。如要確定控制器是否支援特定功能,請針對 controllerFlags 執行對應常數的邏輯 AND。非零的結果表示控制器支援這項功能。

PADDLEBOAT_CONTROLLER_FLAG_TOUCHPAD

如果設定了此旗標位元,控制器就會有整合的觸控板。如果按下觸控板,控制器會在 Paddleboat_Controller_Data.buttonsDown 欄位中設定 PADDLEBOAT_BUTTON_TOUCHPAD 位元。

PADDLEBOAT_CONTROLLER_FLAG_VIRTUAL_MOUSE

如果設定了此旗標位元,控制器會模擬指標裝置。Paddleboat_Controller_Data 結構的 virtualPointer 成員會填入虛擬指標目前的座標。

控管器資料

Paddleboat_getControllerData 函式會接受兩個輸入參數:控制器索引和指向 Paddleboat_Controller_Data 結構的指標。如果 Paddleboat_Controller_Data 順利填入資料,Paddleboat_getControllerInfo 會傳回 PADDLEBOAT_NO_ERROR,否則會傳回適當的錯誤代碼。

Paddleboat_ErrorCode Paddleboat_getControllerData(const int32_t controllerIndex,
  Paddleboat_Controller_Data *controllerData)

Paddleboat_Controller_Data 結構包含控制器目前的控制輸入值。

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;

值範圍

輸入類型 值範圍
指軸 -1.01.0
觸發事件 0.01.0
虛擬指標 0.0 至視窗寬度/高度 (單位為像素)

結構詳細資料

結構成員 說明
buttonsDown Bit-per-button 位元欄位陣列。按鈕位元遮罩常數是在 paddleboat.h 標頭檔案中定義,且開頭為 PADDLEBOAT_BUTTON_
timestamp. 最近一次控制器輸入事件的時間戳記。時間戳記是自時鐘 Epoch 時間起算的微秒時間。
virtualPointer 虛擬指標位置。只有在 controllerFlags 中設定 PADDLEBOAT_CONTROLLER_FLAG_VIRTUAL_MOUSE 旗標時,才有效,否則為 0.0, 0.0