使用游戏控制器库

使用以下函数,通过游戏控制器库向您的游戏中添加游戏控制器支持。

初始化和销毁游戏控制器库

使用 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)

通知库生命周期事件

必须将游戏控制器的生命周期事件 activity 生命周期 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,请通过调用事件处理代码中的Paddleboat_processGameActivityKeyInputEventPaddleboat_processGameActivityMotionInputEvent来转发GameActivityKeyEventGameActivityMotionEvent事件。

int32_t Paddleboat_processGameActivityKeyInputEvent(const void *event,
                                                    const size_t eventSize)
int32_t Paddleboat_processGameActivityMotionInputEvent(const void *event,
                                                       const size_t eventSize)
参数 描述
事件 指向GameActivityKeyEventGameActivityMotionEvent结构体的指针,具体取决于调用哪个函数。
事件大小 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函数采用两个输入参数:控制器索引、缓冲区大小和指向用于存储控制器名称字符串的缓冲区的指针。名称字符串使用UTF-8编码格式化为C字符串。设备名称使用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 之间的值
缓冲区大小 controllerName传递的缓冲区的大小(以字节为单位),名称字符串将被截断(如有必要)以适合缓冲区。
控制器名称 指向大小为bufferSize字节的缓冲区的指针,用于存储控制器名称。名称将使用UTF-8编码存储为C字符串。

控制器设备信息

Paddleboat_getControllerInfo函数采用两个输入参数:控制器索引和指向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成员包含单个位掩码标志和多位组合值的组合。

controllerFlags执行逻辑AND运算与PADDLEBOAT_CONTROLLER_LAYOUT_MASK的结果值可以转换为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 每按钮位字段数组。按钮位掩码常量定义在**paddleboat.h**头文件中,并以PADDLEBOAT_BUTTON_开头。
时间戳 最近一次控制器输入事件的时间戳。时间戳是从时钟纪元开始的微秒数。
virtualPointer 虚拟指针位置。仅当controllerFlags中设置了PADDLEBOAT_CONTROLLER_FLAG_VIRTUAL_MOUSE标志时才有效,否则将为0.0, 0.0