ย้ายข้อมูลจาก NativeActivity เป็นส่วนหนึ่งของชุดเครื่องมือพัฒนาเกม Android
หน้านี้อธิบายวิธีย้ายข้อมูลจาก
NativeActivity
ถึง
GameActivity
ในโปรเจ็กต์เกม Android ของคุณ
GameActivity
อิงตามNativeActivity
จาก Android
พร้อมการปรับปรุงและฟีเจอร์ใหม่ๆ ดังนี้
- รองรับ
Fragment
จาก Jetpack - เพิ่มการสนับสนุน
TextInput
เพื่ออำนวยความสะดวกในการผสานรวมแป้นพิมพ์เสมือน - จัดการการแตะและเหตุการณ์สำคัญในคลาส Java
GameActivity
แทน อินเทอร์เฟซNativeActivity
onInputEvent
ก่อนย้ายข้อมูล เราขอแนะนำให้อ่าน
คู่มือเริ่มต้นใช้งานซึ่งอธิบายวิธีที่
เพื่อตั้งค่าและผสานรวม GameActivity
ในโปรเจ็กต์ของคุณ
การอัปเดตสคริปต์บิลด์ของ Java
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 โปรดอัปเดตระดับ API ถึง 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' }
- เพิ่มไลบรารี
การอัปเดตโค้ด Kotlin หรือ Java
สามารถใช้ NativeActivity
เป็นกิจกรรมเริ่มต้นและสร้างโหมดเต็มหน้าจอ
แอปพลิเคชัน ปัจจุบัน GameActivity จะใช้เป็นสตาร์ทอัพไม่ได้
กิจกรรม แอปต้องดึงคลาสจาก GameActivity
และใช้เป็น
กิจกรรมเริ่มต้น นอกจากนี้คุณต้องแก้ไขการกำหนดค่าเพิ่มเติมสำหรับ
สร้างแอปแบบเต็มหน้าจอ
ขั้นตอนต่อไปนี้จะถือว่าแอปพลิเคชันของคุณใช้ NativeActivity
เป็นโปรแกรมเริ่มต้น
กิจกรรม หากมิได้เป็นเช่นนั้น คุณสามารถข้ามขั้นตอนส่วนใหญ่ได้
สร้างไฟล์ Kotlin หรือ Java เพื่อโฮสต์กิจกรรมสตาร์ทอัพใหม่ ตัวอย่างเช่น โค้ดต่อไปนี้จะสร้าง
MainActivity
เป็นกิจกรรมเริ่มต้นและ โหลดไลบรารีเนทีฟหลักของแอปพลิเคชันlibAndroidGame.so
:Kotlin
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") } } }
Java
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>
ดูคำแนะนำอย่างละเอียดสำหรับโหมดเต็มหน้าจอได้ที่ คู่มืออย่างละเอียดและตัวอย่างการใช้งานใน ที่เก็บตัวอย่างเกม
คำแนะนำการย้ายข้อมูลนี้ไม่ได้เปลี่ยนชื่อไลบรารีเนทีฟ หากคุณเปลี่ยน ให้ตรวจสอบว่าชื่อไลบรารีเนทีฟสอดคล้องกันใน 3 รายการต่อไปนี้ สถานที่ตั้ง:
โค้ด Kotlin หรือ Java:
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 คุณต้องแทนที่ด้วยเวอร์ชันของ GameActivity
จาก native_app_glue
นอกเหนือจากนั้น เราได้บันทึกขั้นตอนทั้งหมด 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_glue
ของ NDK ทั้งหมด เช่น${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)
วิธีแก้ปัญหา Uns DFPLinkError
หากคุณพบ UnsatsifiedLinkError
สำหรับ
ฟังก์ชัน com.google.androidgamesdk.GameActivity.initializeNativeCode()
เพิ่ม
โค้ดนี้ลงในไฟล์ 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
ออกและแทนที่ด้วยโค้ดของ GameActivity การใช้งานInputBuffer
: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_pollAll(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; }
ตรวจสอบและอัปเดตตรรกะที่แนบกับ NativeActivity
AInputEvent
ดังที่แสดงในขั้นตอนก่อนหน้าInputBuffer
ของ GameActivity การประมวลผลอยู่นอกลูปALooper_pollAll()
แทนที่การใช้งาน
android_app::activity->clazz
ด้วยandroid_app:: activity->javaGameActivity
GameActivity ได้เปลี่ยนชื่อ อินสแตนซ์GameActivity
ของ Java
ขั้นตอนเพิ่มเติม
ขั้นตอนก่อนหน้านี้ครอบคลุมฟังก์ชันของ NativeActivity แต่ GameActivity
มี
ฟีเจอร์เพิ่มเติมที่คุณอาจต้องการใช้:
- TextInput
- เกมคอนโทรลเลอร์
- เศษส่วน
- คำสั่ง InSets ในหน้าต่างใหม่ที่กำหนดไว้ใน NativeAppGlueAppCmd
เราขอแนะนำให้คุณสำรวจฟีเจอร์เหล่านี้และนำไปใช้ตามความเหมาะสม เกม
หากมีคำถามหรือคำแนะนำเกี่ยวกับ GameActivity หรือ AGDK อื่นๆ เพื่อสร้างข้อบกพร่องเพื่อแจ้งให้เราทราบ