使用以下函数,通过游戏控制器库向您的游戏中添加游戏控制器支持。
初始化和销毁游戏控制器库
使用 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
检查游戏控制器库是否已成功初始化。它返回一个布尔值。如果为 true,则 API 可供使用。
bool Paddleboat_isInitialized()
在终止应用程序之前,请使用 Paddleboat_destroy
函数关闭游戏控制器库。该函数接受一个参数,即指向附加到当前线程的 JNIEnv
的指针。Paddleboat_init
可以在 Paddleboat_destroy
之后再次调用。
void Paddleboat_destroy(JNIEnv *env)
通知库生命周期事件
必须将游戏控制器的生命周期事件 activity 生命周期 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
,请通过调用事件处理代码中的Paddleboat_processGameActivityKeyInputEvent
或Paddleboat_processGameActivityMotionInputEvent
来转发GameActivityKeyEvent
和GameActivityMotionEvent
事件。
int32_t Paddleboat_processGameActivityKeyInputEvent(const void *event,
const size_t eventSize)
int32_t Paddleboat_processGameActivityMotionInputEvent(const void *event,
const size_t eventSize)
参数 | 描述 |
---|---|
事件
|
指向GameActivityKeyEvent 或GameActivityMotionEvent 结构体的指针,具体取决于调用哪个函数。 |
事件大小
|
在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 之间的值 |
缓冲区大小
|
由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.0 到1.0 |
扳机 | 0.0 到1.0 |
虚拟指针 | 0.0 到窗口宽度/高度(以像素为单位) |
结构体细节
结构体成员 | 描述 |
---|---|
buttonsDown
|
每按钮位字段数组。按钮位掩码常量定义在**paddleboat.h**头文件中,并以PADDLEBOAT_BUTTON_ 开头。 |
时间戳
|
最近一次控制器输入事件的时间戳。时间戳是从时钟纪元开始的微秒数。 |
virtualPointer
|
虚拟指针位置。仅当controllerFlags 中设置了PADDLEBOAT_CONTROLLER_FLAG_VIRTUAL_MOUSE 标志时才有效,否则将为0.0, 0.0 。 |