استخدام مكتبة وحدة تحكّم الألعاب

استخدم الوظائف التالية لإضافة دعم وحدة التحكم في الألعاب إلى لعبتك باستخدام مكتبة وحدة التحكم في الألعاب.

إعداد مكتبة وحدة تحكّم الألعاب وإتلافها

استخدِم الوظيفة Paddleboat_init لإعداد مكتبة وحدة التحكّم في الألعاب.

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 للتحقق مما إذا تم إعداد مكتبة وحدة التحكم في الألعاب بنجاح. فهي تُرجع قيمة منطقية. إذا كانت القيمة true، تكون واجهة برمجة التطبيقات متاحة للاستخدام.

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 مؤشر اختياري (قد يكون فارغًا) لبيانات محدّدة من قِبل المستخدم ومحددة من خلال آخر استدعاء لـ Paddleboat_setControllerStatusCallback.

استدعاء وظيفة تحديث مكتبة وحدة التحكم في الألعاب

يجب استدعاء وظيفة تحديث مكتبة وحدة التحكم في الألعاب، Paddleboat_update، مرة واحدة لكل إطار في اللعبة، ويُفضَّل أن يكون ذلك بالقرب من بداية الإطار. تستخدم الدالة معلَمة واحدة، وهي مؤشر إلى JNIEnv مرتبط بسلسلة المحادثات الحالية.

void Paddleboat_update(JNIEnv *env)

معالجة الأحداث

عند تلقّي أحداث الإدخال، يجب إعادة توجيه اللعبة إلى مكتبة وحدة التحكم في الألعاب لفحصها. تقيّم مكتبة وحدة التحكّم في الألعاب ما إذا كان حدث الإدخال مرتبطًا بأحد أجهزتها المُدارة. تتم معالجة الأحداث من الأجهزة المُدارة واستخدامها.

تتيح مكتبة وحدة التحكم في الألعاب نوعين من أحداث الإدخال: AInputEvents وأحداث الإدخال في GameActivity.

معالجة AInputEvent

يجب إعادة توجيه لعبتك إلى AInputEvents من خلال الاتصال بالعنوان Paddleboat_processInputEvent من رمز التعامل مع الأحداث.

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 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 موقع المؤشر الافتراضي صالحة فقط إذا تم ضبط العلامة PADDLEBOAT_CONTROLLER_FLAG_VIRTUAL_MOUSE في controllerFlags، وإلا ستكون 0.0, 0.0.