از قسمت NativeActivity کیت توسعه بازی اندروید مهاجرت کنید.
این صفحه نحوه مهاجرت از NativeActivity به GameActivity را در پروژه بازی اندروید خود شرح می دهد.
GameActivity مبتنی بر NativeActivity از فریم ورک اندروید است، با پیشرفتها و ویژگیهای جدید:
- از
Fragmentاز Jetpack پشتیبانی می کند. - برای تسهیل یکپارچه سازی صفحه کلید نرم، پشتیبانی
TextInputرا اضافه می کند. - رویدادهای لمسی و کلیدی را در کلاس
GameActivityجاوا به جای رابطNativeActivityonInputEventمدیریت می کند.
قبل از مهاجرت، توصیه میکنیم راهنمای شروع را مطالعه کنید، که نحوه راهاندازی و ادغام GameActivity در پروژه را توضیح میدهد.
به روز رسانی اسکریپت ساخت جاوا
GameActivity به عنوان یک کتابخانه Jetpack توزیع شده است. مطمئن شوید که مراحل بهروزرسانی اسکریپت Gradle را که در راهنمای شروع کار توضیح داده شده است، اعمال کنید:
کتابخانه Jetpack را در فایل
gradle.propertiesپروژه خود فعال کنید:android.useAndroidX=trueبه صورت اختیاری، یک نسخه Prefab را در همان فایل
gradle.propertiesمشخص کنید، برای مثال:android.prefabVersion=2.0.0ویژگی Prefab را در فایل
build.gradleبرنامه خود فعال کنید:android { ... // other configurations buildFeatures.prefab true }وابستگی
GameActivityرا به برنامه خود اضافه کنید:-
coreو کتابخانه هایgames-activityرا اضافه کنید. - اگر حداقل سطح API پشتیبانی شده فعلی شما کمتر از 16 است، آن را به حداقل 16 به روز کنید.
- نسخه SDK کامپایل شده را به نسخه ای که کتابخانه
games-activityنیاز دارد، به روز کنید. Jetpack معمولاً در زمان انتشار به آخرین نسخه SDK نیاز دارد.
فایل
build.gradleبه روز شده شما ممکن است چیزی شبیه به این باشد:android { compiledSdkVersion 33 ... // other configurations. defaultConfig { minSdkVersion 16 } ... // other configurations. buildFeatures.prefab true } dependencies { implementation 'androidx.core:core:1.9.0' implementation 'androidx.games:games-activity:1.2.2' }-
به روز رسانی کد کاتلین یا جاوا
NativeActivity می تواند به عنوان یک فعالیت راه اندازی استفاده شود و یک برنامه تمام صفحه ایجاد کند. در حال حاضر، GameActivity نمی تواند به عنوان فعالیت راه اندازی استفاده شود. برنامه ها باید یک کلاس از GameActivity گرفته و از آن به عنوان فعالیت راه اندازی استفاده کنند. همچنین برای ایجاد یک برنامه تمام صفحه باید تغییرات بیشتری در پیکربندی ایجاد کنید.
مراحل زیر فرض می کنند که برنامه شما از NativeActivity به عنوان فعالیت راه اندازی استفاده می کند. اگر اینطور نیست، می توانید از بسیاری از آنها صرف نظر کنید.
یک فایل Kotlin یا Java برای میزبانی فعالیت راه اندازی جدید ایجاد کنید. برای مثال، کد زیر
MainActivityبه عنوان فعالیت راهاندازی ایجاد میکند و کتابخانه اصلی برنامه،libAndroidGame.soرا بارگیری میکند:کاتلین
class MainActivity : GameActivity() { override fun onResume() { super.onResume() // Use the function recommended from the following page: // https://d.android.com/training/system-ui/immersive hideSystemBars() } companion object { init { System.loadLibrary("AndroidGame") } } }
جاوا
public class MainActivity extends GameActivity { protected void onResume() { super.onResume(); // Use the function recommended from // https://d.android.com/training/system-ui/immersive hideSystemBars(); } static { System.loadLibrary("AndroidGame"); } }
یک تم برنامه تمام صفحه در فایل
res\values\themes.xmlایجاد کنید:<resources xmlns:tools="http://schemas.android.com/tools"> <!-- Base application theme. --> <style name="Application.Fullscreen" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:windowFullscreen">true</item> <item name="android:windowContentOverlay">@null</item>" </style> </resources>تم را روی برنامه در فایل
AndroidManifest.xmlاعمال کنید:<application android:theme=”@style/Application.Fullscreen”> <!-- other configurations not listed here. --> </application>برای دستورالعمل های دقیق برای حالت تمام صفحه، به راهنمای همهجانبه و اجرای نمونه در مخزن بازی-نمونه ها مراجعه کنید.
این راهنمای مهاجرت نام کتابخانه بومی را تغییر نمی دهد. اگر آن را تغییر میدهید، مطمئن شوید که نامهای کتابخانه بومی در سه مکان زیر مطابقت دارند:
کد کاتلین یا جاوا:
System.loadLibrary(“AndroidGame”)AndroidManifest.xml:<meta-data android:name="android.app.lib_name" android:value="AndroidGame" />در داخل فایل اسکریپت ساخت C/C++، برای مثال
CMakeLists.txt:add_library(AndroidGame ...)
به روز رسانی اسکریپت ساخت C/C++
دستورالعمل های این بخش از cmake به عنوان مثال استفاده می کنند. اگر برنامه شما از ndk-build استفاده می کند، باید آنها را به دستورات معادل توضیح داده شده در صفحه مستندات ndk-build نگاشت کنید.
اجرای C/C++ GameActivity یک کد منبع را ارائه کرده است. برای نسخه 1.2.2 بعدی، یک نسخه کتابخانه ایستا ارائه شده است. کتابخانه ایستا نوع انتشار توصیه شده است.
نسخه در داخل AAR با ابزار prefab بسته بندی شده است. کد بومی شامل منابع C/C++ GameActivity و کد native_app_glue است. آنها باید همراه با کد C/C++ برنامه شما ساخته شوند.
برنامههای NativeActivity قبلاً از کد native_app_glue ارسال شده در NDK استفاده میکنند. باید آن را با نسخه native_app_glue GameActivity جایگزین کنید. به غیر از آن، تمام مراحل cmake مستند در راهنمای شروع کار اعمال می شود:
کتابخانه ایستا C/C++ یا کد منبع C/++ را به صورت زیر وارد پروژه خود کنید.
کتابخانه ایستا
در فایل
CMakeLists.txtپروژه خود، کتابخانه استاتیکgame-activityرا به ماژول prefabgame-activity_staticوارد کنید:find_package(game-activity REQUIRED CONFIG) target_link_libraries(${PROJECT_NAME} PUBLIC log android game-activity::game-activity_static)کد منبع
در فایل
CMakeLists.txtپروژه خود، بستهgame-activityرا وارد کرده و آن را به هدف خود اضافه کنید. بستهgame-activityبهlibandroid.soنیاز دارد، بنابراین اگر موجود نیست، باید آن را نیز وارد کنید.find_package(game-activity REQUIRED CONFIG) ... target_link_libraries(... android game-activity::game-activity)تمام ارجاعات به کد
native_app_glueNDK را حذف کنید ، مانند:${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c ... set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate")اگر از نسخه کد منبع استفاده میکنید، فایلهای منبع
GameActivityرا نیز اضافه کنید. در غیر این صورت از این مرحله صرف نظر کنید.get_target_property(game-activity-include game-activity::game-activity INTERFACE_INCLUDE_DIRECTORIES) add_library(${PROJECT_NAME} SHARED main.cpp ${game-activity-include}/game-activity/native_app_glue/android_native_app_glue.c ${game-activity-include}/game-activity/GameActivity.cpp ${game-activity-include}/game-text-input/gametextinput.cpp)
مشکل UnsatisfiedLinkError را حل کنید
اگر برای تابع com.google.androidgamesdk.GameActivity.initializeNativeCode() با UnsatsifiedLinkError مواجه شدید، این کد را به فایل CMakeLists.txt خود اضافه کنید:
set(CMAKE_SHARED_LINKER_FLAGS
"${CMAKE_SHARED_LINKER_FLAGS} -u \
Java_com_google_androidgamesdk_GameActivity_initializeNativeCode")
به روز رسانی کد منبع C/C++
این مراحل را برای جایگزینی مراجع NativeActivity در برنامه خود با GameActivity دنبال کنید:
از
native_app_glueمنتشر شده باGameActivityاستفاده کنید. جستجو و جایگزینی تمام موارد استفادهandroid_native_app_glue.hبا:#include <game-activity/native_app_glue/android_native_app_glue.h>فیلتر رویداد حرکتی و فیلتر رویداد کلیدی را روی
NULLتنظیم کنید تا برنامه شما بتواند رویدادهای ورودی را از همه دستگاههای ورودی دریافت کند. شما معمولاً این کار را در تابعandroid_main()انجام می دهید:void android_main(android_app* app) { ... // other init code. android_app_set_key_event_filter(app, NULL); android_app_set_motion_event_filter(app, NULL); ... // additional init code, and game loop code. }کد مربوط به
AInputEventرا حذف کرده و با اجرایInputBufferGameActivity جایگزین کنید:while (true) { // Read all pending events. int events; struct android_poll_source* source; // If not animating, block forever waiting for events. // If animating, loop until all events are read, then continue // to draw the next frame of animation. while ((ALooper_pollOnce(engine.animating ? 0 : -1, nullptr, &events, (void**)&source)) >= 0) { // Process this app cycle or inset change event. if (source) { source->process(source->app, source); } ... // Other processing. // Check if app is exiting. if (state->destroyRequested) { engine_term_display(&engine); return; } } // Process input events if there are any. engine_handle_input(state); if (engine.animating) { // Draw a game frame. } } // Implement input event handling function. static int32_t engine_handle_input(struct android_app* app) { auto* engine = (struct engine*)app->userData; auto ib = android_app_swap_input_buffers(app); if (ib && ib->motionEventsCount) { for (int i = 0; i < ib->motionEventsCount; i++) { auto *event = &ib->motionEvents[i]; int32_t ptrIdx = 0; switch (event->action & AMOTION_EVENT_ACTION_MASK) { case AMOTION_EVENT_ACTION_POINTER_DOWN: case AMOTION_EVENT_ACTION_POINTER_UP: // Retrieve the index for the starting and the ending of any secondary pointers ptrIdx = (event->action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; case AMOTION_EVENT_ACTION_DOWN: case AMOTION_EVENT_ACTION_UP: engine->state.x = GameActivityPointerAxes_getAxisValue( &event->pointers[ptrIdx], AMOTION_EVENT_AXIS_X); engine->state.y = GameActivityPointerAxes_getAxisValue( &event->pointers[ptrIdx], AMOTION_EVENT_AXIS_Y); break; case AMOTION_EVENT_ACTION_MOVE: // Process the move action: the new coordinates for all active touch pointers // are inside the event->pointers[]. Compare with our internally saved // coordinates to find out which pointers are actually moved. Note that there is // no index embedded inside event->action for AMOTION_EVENT_ACTION_MOVE (there // might be multiple pointers moved at the same time). ... break; } } android_app_clear_motion_events(ib); } // Process the KeyEvent in a similar way. ... return 0; }منطق پیوست شده به
AInputEventNativeActivity را بررسی و بهروزرسانی کنید. همانطور که در مرحله قبل نشان داده شد، پردازشInputBufferGameActivity خارج از حلقهALooper_pollOnce()است.android_app::activity->clazzusage را باandroid_app:: activity->javaGameActivityجایگزین کنید. GameActivity نمونه JavaGameActivityرا تغییر نام می دهد.
مراحل اضافی
مراحل قبلی عملکرد NativeActivity را پوشش می دهد، اما GameActivity دارای ویژگی های اضافی است که ممکن است بخواهید از آنها استفاده کنید:
- TextInput .
- کنترلر بازی
- قطعه .
- پنجره جدید دستورات InSets تعریف شده در NativeAppGlueAppCmd .
توصیه میکنیم این ویژگیها را بررسی کنید و آنها را متناسب با بازیهای خود بکار ببرید.
اگر سؤال یا توصیهای برای GameActivity یا سایر کتابخانههای AGDK دارید، یک اشکال ایجاد کنید تا به ما اطلاع دهید.