নেটিভঅ্যাক্টিভিটি থেকে মাইগ্রেট করুন , যা অ্যান্ড্রয়েড গেম ডেভেলপমেন্ট কিট- এর একটি অংশ।

এই পৃষ্ঠায় আপনার অ্যান্ড্রয়েড গেম প্রজেক্টে NativeActivity থেকে GameActivity তে মাইগ্রেট করার পদ্ধতি বর্ণনা করা হয়েছে।

GameActivity অ্যান্ড্রয়েড ফ্রেমওয়ার্কের NativeActivity উপর ভিত্তি করে তৈরি, এবং এতে কিছু উন্নত বৈশিষ্ট্য ও নতুন সংযোজন রয়েছে:

  • জেটপ্যাকের Fragment সমর্থন করে।
  • সফট কিবোর্ড ইন্টিগ্রেশন সহজ করার জন্য TextInput সাপোর্ট যোগ করা হয়েছে।
  • NativeActivity onInputEvent ইন্টারফেসের পরিবর্তে GameActivity জাভা ক্লাসে টাচ এবং কী ইভেন্টগুলো পরিচালনা করে।

মাইগ্রেট করার আগে, আমরা গেট স্টার্টেড গাইডটি পড়ার পরামর্শ দিই, যেখানে আপনার প্রোজেক্টে GameActivity কীভাবে সেট আপ এবং ইন্টিগ্রেট করতে হয় তা বর্ণনা করা হয়েছে।

জাভা বিল্ড স্ক্রিপ্ট আপডেট

GameActivity একটি Jetpack লাইব্রেরি হিসেবে বিতরণ করা হয়। গেট স্টার্টেড গাইডে বর্ণিত গ্রেডল স্ক্রিপ্ট আপডেট করার ধাপগুলো অবশ্যই অনুসরণ করুন:

  1. আপনার প্রোজেক্টের gradle.properties ফাইলে Jetpack লাইব্রেরিটি সক্রিয় করুন:

    android.useAndroidX=true
    
  2. ঐচ্ছিকভাবে, একই gradle.properties ফাইলে একটি প্রিফ্যাব ভার্সন নির্দিষ্ট করে দিন, উদাহরণস্বরূপ:

    android.prefabVersion=2.0.0
    
  3. আপনার অ্যাপের build.gradle ফাইলে Prefab ফিচারটি সক্রিয় করুন:

    android {
        ... // other configurations
        buildFeatures.prefab true
    }
    
  4. আপনার অ্যাপ্লিকেশনে GameActivity ডিপেন্ডেন্সিটি যোগ করুন:

    1. core এবং games-activity লাইব্রেরিগুলো যোগ করুন।
    2. আপনার বর্তমান সর্বনিম্ন সমর্থিত এপিআই লেভেল যদি ১৬-এর কম হয়, তবে তা আপডেট করে কমপক্ষে ১৬ করুন।
    3. কম্পাইল করা SDK সংস্করণটিকে games-activity লাইব্রেরির প্রয়োজনীয় সংস্করণে আপডেট করুন। রিলিজ বিল্ডের সময় জেটপ্যাক সাধারণত সর্বশেষ 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 ব্যবহার করে। যদি তা না হয়, তবে আপনি এগুলোর বেশিরভাগই বাদ দিতে পারেন।

  1. নতুন স্টার্টআপ অ্যাক্টিভিটি হোস্ট করার জন্য একটি কোটলিন বা জাভা ফাইল তৈরি করুন। উদাহরণস্বরূপ, নিম্নলিখিত কোডটি 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");
          }
      }
  2. 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>
    
  3. AndroidManifest.xml ফাইলে অ্যাপ্লিকেশনটিতে থিমটি প্রয়োগ করুন:

    <application  android:theme=”@style/Application.Fullscreen”>
         <!-- other configurations not listed here. -->
    </application>
    

    ফুল স্ক্রিন মোডের বিস্তারিত নির্দেশাবলীর জন্য, games-samples রিপো- তে থাকা ইমারসিভ গাইড এবং উদাহরণ বাস্তবায়ন দেখুন।

এই মাইগ্রেশন গাইডটি নেটিভ লাইব্রেরির নাম পরিবর্তন করে না। যদি আপনি এটি পরিবর্তন করেন, তবে নিশ্চিত করুন যে নিম্নলিখিত তিনটি স্থানে নেটিভ লাইব্রেরির নামগুলো সামঞ্জস্যপূর্ণ থাকে:

  • কোটলিন বা জাভা কোড:

    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 ডকুমেন্টেশন পৃষ্ঠায় বর্ণিত সমতুল্য কমান্ডগুলোর সাথে মিলিয়ে নিতে হবে।

GameActivity-এর C/C++ ইমপ্লিমেন্টেশনের জন্য সোর্স কোড রিলিজ দেওয়া হয়ে আসছে। ভার্সন ১.২.২ এবং তার পরবর্তী সংস্করণগুলোর জন্য একটি স্ট্যাটিক লাইব্রেরি রিলিজ দেওয়া হয়। স্ট্যাটিক লাইব্রেরিই হলো প্রস্তাবিত রিলিজ টাইপ।

রিলিজটি prefab ইউটিলিটি সহ AAR ফাইলের ভিতরে প্যাক করা আছে। নেটিভ কোডের মধ্যে GameActivity-এর C/C++ সোর্স এবং native_app_glue কোড অন্তর্ভুক্ত রয়েছে। আপনার অ্যাপ্লিকেশনের C/C++ কোডের সাথে এগুলোকেও বিল্ড করতে হবে।

NativeActivity অ্যাপ্লিকেশনগুলো ইতিমধ্যেই NDK-এর সাথে আসা native_app_glue কোড ব্যবহার করে। আপনাকে অবশ্যই এটি GameActivity-এর native_app_glue সংস্করণ দিয়ে প্রতিস্থাপন করতে হবে। এছাড়া, গেটিং স্টার্টেড গাইডে বর্ণিত cmake সমস্ত ধাপ প্রযোজ্য হবে:

  • নিম্নলিখিতভাবে আপনার প্রজেক্টে C/C++ স্ট্যাটিক লাইব্রেরি অথবা C/++ সোর্স কোড ইম্পোর্ট করুন।

    স্থির গ্রন্থাগার

    আপনার প্রোজেক্টের CMakeLists.txt ফাইলে, game-activity_static প্রিফ্যাব মডিউলের মধ্যে game-activity স্ট্যাটিক লাইব্রেরিটি ইম্পোর্ট করুন:

    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)
    
  • NDK-এর native_app_glue কোডের সমস্ত উল্লেখ মুছে ফেলুন , যেমন:

    ${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 দিয়ে প্রতিস্থাপন করতে এই ধাপগুলি অনুসরণ করুন:

  • GameActivity সাথে প্রকাশিত native_app_glue ব্যবহার করুন। 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_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;
    }
    
  • NativeActivity-এর AInputEvent সাথে সংযুক্ত লজিকটি পর্যালোচনা ও আপডেট করুন। পূর্ববর্তী ধাপে যেমন দেখানো হয়েছে, GameActivity-এর InputBuffer প্রসেসিং ALooper_pollOnce() লুপের বাইরে থাকে।

  • android_app::activity->clazz এর পরিবর্তে android_app:: activity->javaGameActivity ব্যবহার করুন। GameActivity জাভা GameActivity ইনস্ট্যান্সটির নাম পরিবর্তন করে।

অতিরিক্ত পদক্ষেপ

পূর্ববর্তী ধাপগুলোতে NativeActivity-এর কার্যকারিতা বর্ণনা করা হয়েছে, কিন্তু GameActivity আরও কিছু অতিরিক্ত বৈশিষ্ট্য রয়েছে যা আপনি ব্যবহার করতে চাইতে পারেন:

আমরা এই বৈশিষ্ট্যগুলো অন্বেষণ করতে এবং আপনার গেমের জন্য প্রয়োজন অনুযায়ী সেগুলো গ্রহণ করার পরামর্শ দিই।

GameActivity বা অন্যান্য AGDK লাইব্রেরি সম্পর্কে আপনার কোনো প্রশ্ন বা সুপারিশ থাকলে, আমাদের জানানোর জন্য একটি বাগ তৈরি করুন।