Чтобы добавить в игру поддержку контроллера, используйте библиотеку Game Controller и следующие функции:
Инициализация и уничтожение библиотеки Game Controller
Используйте функцию Paddleboat_init, чтобы инициализировать библиотеку Game Controller.
Paddleboat_ErrorCode Paddleboat_init(JNIEnv *env, jobject jcontext)
Функция Paddleboat_init принимает два параметра:
- Указатель на
JNIEnv, прикрепленный к текущему потоку - Ссылка на объект JNI
jobjectдля производного классаContext. Допустим любой объект производного классаContext, в том числеActivity,NativeActivityилиGameActivity.
Paddleboat_init возвращает PADDLEBOAT_NO_ERROR, если инициализация прошла успешно, в противном случае возвращается соответствующий код ошибки.
Вы можете использовать Paddleboat_isInitialized, чтобы проверить, успешно ли инициализирована библиотека Game Controller. Функция возвращает логическое значение. Если указано значение true, API доступен для использования.
bool Paddleboat_isInitialized()
Перед завершением работы приложения используйте функцию Paddleboat_destroy, чтобы закрыть библиотеку контроллера. Функция принимает один параметр – указатель на объект JNIEnv, прикрепленный к текущему потоку.
Paddleboat_init можно вызвать снова после Paddleboat_destroy.
void Paddleboat_destroy(JNIEnv *env)
Как сообщать библиотеке о событиях жизненного цикла
Библиотека Game Controller должна получать информацию о жизненном цикле объекта activity, а также о событиях onStop и onStart.
Вызовите функции
Paddleboat_onStop
и
Paddleboat_onStart
из кода обработчика событий остановки и запуска. Обе функции принимают один параметр – указатель на объект JNIEnv, прикрепленный к текущему потоку.
void Paddleboat_onStop(JNIEnv *env)
void Paddleboat_onStart(JNIEnv *env)
Как зарегистрировать или удалить обратный вызов статуса контроллера
Библиотека Game Controller использует обратный вызов статуса контроллера, чтобы уведомлять игру о подключении или отключении контроллера. Одновременно поддерживается только один обратный вызов статуса контроллера.
- Чтобы зарегистрировать обратный вызов статуса контроллера или заменить ранее зарегистрированный обратный вызов новой функцией обратного вызова, вызовите функцию
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)
Обработка событий
При получении событий ввода игра должна пересылать их в библиотеку Game Controller для проверки. Библиотека Game Controller определяет, связано ли событие ввода с одним из управляемых ею устройств. События с управляемых устройств обрабатываются и используются.
Библиотека Game Controller поддерживает два типа событий ввода: AInputEvents и GameActivity.
Обработка событий ввода AInputEvent
Ваша игра должна пересылать AInputEvents, вызывая
Paddleboat_processInputEvent
из кода обработчика событий.
int32_t Paddleboat_processInputEvent(const AInputEvent *event)
Paddleboat_processInputEvent возвращает 0, если событие было проигнорировано, и 1, если оно было обработано библиотекой Game Controller.
Обработка событий 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, если оно было обработано и использовано библиотекой Game Controller.
Для атрибута "ось движения" GameActivity необходимо указать активную ось движения с помощью функции GameActivityPointerAxes_enableAxis. Вызов Paddleboat_getActiveAxisMask возвращает битовую маску активных осей движения, используемых подключенными контроллерами.
uint64_t Paddleboat_getActiveAxisMask()
Пример того, как это можно сделать, приведен в образце библиотеки Game Controller, в котором используется 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;
}
}
}
Чтение данных контроллеров
Библиотека Game Controller использует индексное значение для ссылки на определенный контроллер. Допустимые значения индекса: от 0 до PADDLEBOAT_MAX_CONTROLLERS - 1. Функция Paddleboat_getControllerStatus определяет статус указанного индекса контроллера.
Paddleboat_ControllerStatus Paddleboat_getControllerStatus(
const int32_t controllerIndex)
Существует три функции для чтения информации с подключенного контроллера.
- Функция
Paddleboat_getControllerNameполучает название устройства контроллера. - Функция
Paddleboat_getControllerInfoполучает данные о самом контроллере. - Функция
Paddleboat_getControllerDataполучает текущее состояние входов контроллера.
Название контроллера
Функция 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 содержит комбинацию отдельных битовых масок и многобитовых значений.
Выполнение логической операции AND над controllerFlags и 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
};
Следующие константы определяют биты возможностей. Чтобы определить, поддерживает ли контроллер определенную функцию, выполните логическую операцию AND соответствующей константы с controllerFlags. Ненулевой результат означает, что контроллер поддерживает эту функцию.
PADDLEBOAT_CONTROLLER_FLAG_TOUCHPAD
Если этот бит установлен, у контроллера есть встроенная сенсорная панель. Если нажать на сенсорную панель, контроллер установит бит PADDLEBOAT_BUTTON_TOUCHPAD в поле Paddleboat_Controller_Data.buttonsDown.
PADDLEBOAT_CONTROLLER_FLAG_VIRTUAL_MOUSE
Если этот флаг установлен, контроллер эмулирует указатель. Поле virtualPointer структуры Paddleboat_Controller_Data заполняется текущими координатами виртуального указателя.
Данные контроллера
Функция 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. |