使用以下函数将游戏手柄支持添加到您的游戏中,使用游戏手柄库。
初始化和销毁游戏手柄库
使用 Paddleboat_init
函数初始化游戏手柄库。
Paddleboat_ErrorCode Paddleboat_init(JNIEnv *env, jobject jcontext)
Paddleboat_init
接受两个参数
- 指向附加到当前线程的
JNIEnv
的指针 - 指向
Context
派生类的jobject
JNI 对象引用。任何Context
派生类对象都是有效的,包括但不限于Activity
、NativeActivity
或GameActivity
。
Paddleboat_init
如果初始化成功,则返回 PADDLEBOAT_NO_ERROR
,否则返回相应的错误代码。
您可以使用 Paddleboat_isInitialized
检查游戏手柄库是否已成功初始化。它返回一个布尔值。如果为真,则 API 可供使用。
bool Paddleboat_isInitialized()
在终止应用程序之前,使用 Paddleboat_destroy
函数关闭游戏手柄库。该函数接受一个参数,即指向附加到当前线程的 JNIEnv
的指针。 Paddleboat_init
可以在 Paddleboat_destroy
之后再次调用。
void Paddleboat_destroy(JNIEnv *env)
通知库生命周期事件
游戏手柄库必须通知 活动生命周期 onStop
和 onStart
事件。从您的停止和启动事件处理代码中调用 Paddleboat_onStop
和 Paddleboat_onStart
函数。这两个函数都接受一个参数:指向附加到当前线程的 JNIEnv
的指针。
void Paddleboat_onStop(JNIEnv *env)
void Paddleboat_onStart(JNIEnv *env)
注册或删除手柄状态回调
游戏手柄库使用手柄状态回调来通知游戏何时连接或断开手柄。它一次只支持一个手柄状态回调。
- 要注册手柄状态回调或用新回调函数替换任何先前注册的回调函数,请调用
Paddleboat_setControllerStatusCallback
函数。 - 要删除任何当前注册的回调函数,请传递
NULL
或nullptr
。 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)
处理事件
在接收输入事件时,您的游戏需要将这些事件转发给游戏手柄库以供检查。游戏手柄库会评估输入事件是否与它管理的其中一个设备相关联。来自管理设备的事件将被处理和使用。
游戏手柄库支持两种类型的输入事件:AInputEvents
和 GameActivity
输入事件。
AInputEvent 处理
您的游戏应该通过从您的事件处理代码中调用 Paddleboat_processInputEvent
来转发 AInputEvents
。
int32_t Paddleboat_processInputEvent(const AInputEvent *event)
Paddleboat_processInputEvent
如果事件被忽略,则返回 0
;如果事件被游戏手柄库处理和使用,则返回 1
。
GameActivity 事件处理
如果您的游戏使用 GameActivity
,请通过从您的事件处理代码中调用 GameActivityKeyEvent
和 GameActivityMotionEvent
事件来转发 Paddleboat_processGameActivityKeyInputEvent
或 Paddleboat_processGameActivityMotionInputEvent
。
int32_t Paddleboat_processGameActivityKeyInputEvent(const void *event,
const size_t eventSize)
int32_t Paddleboat_processGameActivityMotionInputEvent(const void *event,
const size_t eventSize)
参数 | 描述 |
---|---|
event
|
指向 GameActivityKeyEvent 或 GameActivityMotionEvent 结构体的指针,具体取决于调用哪个函数。 |
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;
}
}
}
读取控制器
游戏控制器库使用索引值来引用特定控制器。有效的索引值范围从 0
到 PADDLEBOAT_MAX_CONTROLLERS - 1
。 Paddleboat_getControllerStatus
函数确定指定控制器索引的状态。
Paddleboat_ControllerStatus Paddleboat_getControllerStatus(
const int32_t controllerIndex)
有三个函数用于从连接的控制器读取信息。
Paddleboat_getControllerName
函数检索控制器的名称。Paddleboat_getControllerInfo
函数检索有关控制器本身的数据。Paddleboat_getControllerData
函数检索控制器输入的当前状态。
控制器名称
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 之间的值 |
bufferSize
|
由 controllerName 传递的缓冲区的大小(以字节为单位),名称字符串将被截断(如果必要)以适应缓冲区。 |
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
与 PADDLEBOAT_CONTROLLER_LAYOUT_MASK
的逻辑 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.0 到 1.0 |
扳机 | 0.0 到 1.0 |
虚拟指针 | 0.0 到窗口宽度/高度(以像素为单位) |
结构细节
结构成员 | 描述 |
---|---|
buttonsDown
|
每按钮位域数组。按钮位掩码常量在 paddleboat.h 中定义。头文件,并以 PADDLEBOAT_BUTTON_ 开头。 |
timestamp.
|
最近控制器输入事件的时间戳。时间戳是自时钟纪元以来的微秒数。 |
virtualPointer
|
虚拟指针位置。仅在 controllerFlags 中设置了 PADDLEBOAT_CONTROLLER_FLAG_VIRTUAL_MOUSE 标志时才有效,否则将为 0.0, 0.0 。 |