আপনার গেমে সংরক্ষিত গেম যোগ করুন

Google সাইন-ইন API বন্ধ করার পর, আমরা ২০২৬ সালে গেমস v1 SDK সরিয়ে ফেলছি। ২০২৫ সালের ফেব্রুয়ারির পর, আপনি Google Play তে গেমস v1 SDK-এর সাথে নতুনভাবে সংহত করা শিরোনাম প্রকাশ করতে পারবেন না। আমরা আপনাকে এর পরিবর্তে গেমস v2 SDK ব্যবহার করার পরামর্শ দিচ্ছি।
পূর্ববর্তী গেম v1 ইন্টিগ্রেশন সহ বিদ্যমান শিরোনামগুলি কয়েক বছর ধরে কাজ করলেও, আপনাকে জুন 2025 থেকে v2 তে স্থানান্তরিত হতে উৎসাহিত করা হচ্ছে।
এই নির্দেশিকাটি Play Games Services v1 SDK ব্যবহারের জন্য। Play Games Services v2 এর জন্য C++ SDK এখনও উপলব্ধ নয়।

এই নির্দেশিকাটি আপনাকে দেখায় কিভাবে C++ অ্যাপ্লিকেশনে Saved Games পরিষেবা ব্যবহার করে একজন খেলোয়াড়ের গেমের অগ্রগতির ডেটা সংরক্ষণ এবং লোড করতে হয়। গেমপ্লে চলাকালীন যেকোনো সময়ে আপনি এই পরিষেবাটি ব্যবহার করে খেলোয়াড়ের গেমের অগ্রগতি স্বয়ংক্রিয়ভাবে লোড এবং সংরক্ষণ করতে পারেন। এই পরিষেবাটি খেলোয়াড়দের একটি বিদ্যমান সেভ গেম আপডেট বা পুনরুদ্ধার করতে, অথবা একটি নতুন তৈরি করতে একটি ব্যবহারকারী ইন্টারফেস ট্রিগার করতে সক্ষম করে।

শুরু করার আগে

যদি আপনি ইতিমধ্যেই এটি না করে থাকেন, তাহলে Saved Games গেমের ধারণাগুলি পর্যালোচনা করা আপনার জন্য সহায়ক হতে পারে।

সংরক্ষিত গেমস API ব্যবহার করে কোডিং শুরু করার আগে:

ডেটা ফর্ম্যাট এবং ক্রস-প্ল্যাটফর্ম সামঞ্জস্য

গুগলের সার্ভারে সংরক্ষণ করা গেমসের সংরক্ষিত ডেটা অবশ্যই std::vector<uint8_t> ফর্ম্যাটে হতে হবে। সংরক্ষিত গেমস পরিষেবা ক্রস-প্ল্যাটফর্ম সামঞ্জস্যের জন্য আপনার ডেটা এনকোড করার যত্ন নেয়; অ্যান্ড্রয়েড অ্যাপ্লিকেশনগুলি কোনও ক্রস-প্ল্যাটফর্ম সামঞ্জস্যের সমস্যা ছাড়াই বাইট অ্যারের মতো একই ডেটা পড়তে পারে।

আপনার সংরক্ষিত গেমস ডেটার জন্য ডেটা ফর্ম্যাট নির্বাচন করার সময় প্ল্যাটফর্ম-নির্দিষ্ট ফর্ম্যাট ব্যবহার করা এড়িয়ে চলুন। আমরা আপনাকে XML বা JSON এর মতো ডেটা ফর্ম্যাট ব্যবহার করার জন্য দৃঢ়ভাবে উৎসাহিত করছি, যার একাধিক প্ল্যাটফর্মে শক্তিশালী লাইব্রেরি সমর্থন রয়েছে।

সংরক্ষিত গেম পরিষেবা সক্ষম করুন

Saved Games পরিষেবা ব্যবহার করার আগে, আপনাকে প্রথমে এটিতে অ্যাক্সেস সক্ষম করতে হবে। এটি করার জন্য, gpg::GameServices::Builder দিয়ে পরিষেবা তৈরি করার সময় EnableSnapshots() কল করুন। এটি পরবর্তী auth ইভেন্টে Saved Games দ্বারা প্রয়োজনীয় অতিরিক্ত auth স্কোপ সক্ষম করবে।

সংরক্ষিত গেমগুলি প্রদর্শন করুন

আপনার গেমে, আপনি এমন একটি বিকল্প প্রদান করতে পারেন যা খেলোয়াড়রা সংরক্ষিত গেমগুলি সংরক্ষণ বা পুনরুদ্ধার করার জন্য ট্রিগার করতে পারে। যখন খেলোয়াড়রা এই বিকল্পটি নির্বাচন করেন, তখন আপনার গেমটি এমন একটি স্ক্রিন নিয়ে আসবে যা বিদ্যমান সেভ স্লটগুলি প্রদর্শন করবে এবং খেলোয়াড়দের এই স্লটগুলির একটিতে সংরক্ষণ করতে বা লোড করতে, অথবা একটি নতুন সংরক্ষিত গেম তৈরি করতে অনুমতি দেবে। এটি করার জন্য নিম্নলিখিত পদ্ধতিটি ব্যবহার করুন:

  SnapshotManager::ShowSelectUIOperation(...)

সংরক্ষিত গেম নির্বাচন UI খেলোয়াড়দের একটি নতুন সংরক্ষিত গেম তৈরি করতে, বিদ্যমান সংরক্ষিত গেমগুলির বিশদ দেখতে এবং পূর্ববর্তী সংরক্ষিত গেমগুলি লোড করতে দেয়।

  SnapshotManager::SnapshotSelectUIResponse response;
  if (IsSuccess(response.status)) {
  if (response.data.Valid()) {
    LogI("Description: %s", response.data.Description().c_str());
    LogI("FileName %s", response.data.FileName().c_str());
    //Opening the snapshot data
    
  } else {
    LogI("Creating new snapshot");
    
  }
} else {
  LogI("ShowSelectUIOperation returns an error %d", response.status);
}

নিম্নলিখিত উদাহরণটি কীভাবে ডিফল্ট সংরক্ষিত গেমস UI দেখাতে হয় এবং প্লেয়ারের UI নির্বাচন পরিচালনা করতে হয় তা ব্যাখ্যা করে:

  service_->Snapshots().ShowSelectUIOperation(
  ALLOW_CREATE_SNAPSHOT,
  ALLOW_DELETE_SNAPSHOT,
  MAX_SNAPSHOTS,
  SNAPSHOT_UI_TITLE,
  [this](gpg::SnapshotManager::SnapshotSelectUIResponse const & response) {
  
      }

উপরের উদাহরণে, যদি ALLOW_CREATE_SNAPSHOT true হয় এবং MAX_SNAPSHOTS ব্যবহারকারীর তৈরি করা স্ন্যাপশটের প্রকৃত সংখ্যার চেয়ে বেশি হয়, তাহলে ডিফল্ট স্ন্যাপশট UI খেলোয়াড়দের একটি নতুন সেভ গেম তৈরি করার জন্য একটি বোতাম প্রদান করে, বিদ্যমান একটি নির্বাচন করার পরিবর্তে। (প্রদর্শিত হলে, বোতামটি UI এর নীচে থাকে।) যখন একজন খেলোয়াড় এই বোতামে ক্লিক করেন, তখন SnapshotSelectUIResponse প্রতিক্রিয়া বৈধ থাকে কিন্তু এতে কোনও ডেটা থাকে না।

সংরক্ষিত গেমগুলি খুলুন এবং পড়ুন

একটি সংরক্ষিত গেম অ্যাক্সেস করতে এবং এর বিষয়বস্তু পড়তে বা পরিবর্তন করতে, প্রথমে সেই সংরক্ষিত গেমটির প্রতিনিধিত্বকারী SnapshotMetadata অবজেক্টটি খুলুন। এরপর, SnapshotManager::Read*() পদ্ধতিটি কল করুন।

নিম্নলিখিত উদাহরণে একটি সংরক্ষিত খেলা কীভাবে খুলতে হয় তা দেখানো হয়েছে:

  LogI("Opening file");
  service_->Snapshots()
  .Open(current_snapshot_.FileName(),
               gpg::SnapshotConflictPolicy::BASE_WINS,
        [this](gpg::SnapshotManager::OpenResponse const & response) {
           LogI("Reading file");
           gpg::SnapshotManager::ReadResponse responseRead =
           service_->Snapshots().ReadBlocking(response.data);
          
        }

ডেটা দ্বন্দ্ব সনাক্ত করুন এবং সমাধান করুন

যখন আপনি একটি SnapshotMetadata অবজেক্ট খোলেন, তখন Saved Games পরিষেবা সনাক্ত করে যে কোনও বিরোধপূর্ণ সংরক্ষিত গেম বিদ্যমান কিনা। যখন কোনও খেলোয়াড়ের স্থানীয় ডিভাইসে সংরক্ষিত সংরক্ষিত গেমটি Google এর সার্ভারে সংরক্ষিত রিমোট সংস্করণের সাথে সিঙ্কের বাইরে থাকে তখন ডেটা বিরোধ দেখা দিতে পারে।

একটি সংরক্ষিত গেম খোলার সময় আপনি যে দ্বন্দ্ব নীতিটি নির্দিষ্ট করেন তা সংরক্ষিত গেম পরিষেবাকে ডেটা দ্বন্দ্ব কীভাবে স্বয়ংক্রিয়ভাবে সমাধান করতে হয় তা বলে। নীতিটি নিম্নলিখিতগুলির মধ্যে একটি হতে পারে:

দ্বন্দ্ব নীতি বিবরণ
SnapshotConflictPolicy::MANUAL এর অর্থ হল সংরক্ষিত গেম পরিষেবাটি কোনও রেজোলিউশন অ্যাকশন করবে না। পরিবর্তে, আপনার গেমটি একটি কাস্টম মার্জ করবে।
SnapshotConflictPolicy::LONGEST_PLAYTIME এর অর্থ হল, সংরক্ষিত গেমস পরিষেবাটি সর্বাধিক খেলার সময় মান সহ সংরক্ষিত গেমটি বেছে নেবে।
SnapshotConflictPolicy::BASE_WINS ইঙ্গিত করে যে সংরক্ষিত গেমস পরিষেবাটি মূল সংরক্ষিত গেমটি বেছে নেবে।
SnapshotConflictPolicy::REMOTE_WINS এর অর্থ হল, সংরক্ষিত গেম পরিষেবাটি রিমোট সেভ করা গেমটি বেছে নেবে। রিমোট ভার্সন হল সংরক্ষিত গেমের একটি ভার্সন যা খেলোয়াড়ের যেকোনো একটি ডিভাইসে সনাক্ত করা হয় এবং বেস ভার্সনের তুলনায় এর টাইমস্ট্যাম্প আরও সাম্প্রতিক।

যদি আপনি GPGSnapshotConflictPolicyManual ব্যতীত অন্য কোনও দ্বন্দ্ব নীতি নির্দিষ্ট করে থাকেন, তাহলে Saved Games পরিষেবা সংরক্ষিত গেমটিকে একত্রিত করবে এবং SnapshotManager::OpenResponse মানের মাধ্যমে আপডেট হওয়া সংস্করণটি ফিরিয়ে দেবে। আপনার গেমটি সংরক্ষিত গেমটি খুলতে পারে, এতে লিখতে পারে, তারপর SnapshotManager::Commit(...) পদ্ধতিতে কল করে Google এর সার্ভারে সংরক্ষিত গেমটি কমিট করতে পারে।

একটি কাস্টম মার্জ সম্পাদন করুন

যদি আপনি SnapshotConflictPolicy::MANUAL দ্বন্দ্ব নীতি হিসেবে নির্দিষ্ট করে থাকেন, তাহলে সংরক্ষিত গেমটিতে আরও পঠন বা লেখার ক্রিয়াকলাপ সম্পাদন করার আগে আপনার গেমটিকে অবশ্যই সনাক্ত হওয়া যেকোনো ডেটা দ্বন্দ্ব সমাধান করতে হবে।

এই ক্ষেত্রে, যখন কোনও ডেটা দ্বন্দ্ব সনাক্ত করা হয়, তখন পরিষেবাটি SnapshotManager::OpenResponse এর মাধ্যমে নিম্নলিখিত পরামিতিগুলি ফেরত দেয়:

  • এই দ্বন্দ্বটি অনন্যভাবে সনাক্ত করার জন্য একটি conflict_id (সংরক্ষিত গেমের চূড়ান্ত সংস্করণটি তৈরি করার সময় আপনি এই মানটি ব্যবহার করবেন);
  • সংরক্ষিত গেমটির পরস্পরবিরোধী বেস ভার্সন; এবং,
  • সংরক্ষিত গেমটির বিরোধপূর্ণ রিমোট সংস্করণ।

আপনার গেমটিকে কোন ডেটা সংরক্ষণ করতে হবে তা নির্ধারণ করতে হবে, তারপর SnapshotManager::ResolveConflictBlocking() পদ্ধতিতে কল করে চূড়ান্ত সংস্করণটি Google এর সার্ভারে কমিট/সমাধান করতে হবে।

    //Resolve conflict
    gpg::SnapshotManager::OpenResponse resolveResponse =
        manager.ResolveConflictBlocking(openResponse.conflict_base, metadata_change,
                                  openResponse.conflict_id);

সংরক্ষিত গেমগুলি লিখুন

একটি সংরক্ষিত খেলা লিখতে, প্রথমে সেই সংরক্ষিত খেলাটির প্রতিনিধিত্বকারী SnapshotMetadata অবজেক্টটি খুলুন, সনাক্ত হওয়া যেকোনো ডেটা দ্বন্দ্ব সমাধান করুন, তারপর আপনার সংরক্ষিত খেলায় পরিবর্তনগুলি কমিট করার জন্য SnapshotManager::Commit() পদ্ধতিতে কল করুন।

নিম্নলিখিত উদাহরণটি দেখায় কিভাবে আপনি একটি পরিবর্তন তৈরি করতে পারেন এবং একটি সংরক্ষিত খেলা কমিট করতে পারেন।

  1. প্রথমে, আমরা যে স্ন্যাপশটটি সম্পাদনা করতে চাই তা খুলুন, এবং নিশ্চিত করুন যে বেসটি বেছে নিয়ে সমস্ত দ্বন্দ্ব সমাধান করা হয়েছে।

    service_->Snapshots().Open(
          file_name,
          gpg::SnapshotConflictPolicy::BASE_WINS,
          [this](gpg::SnapshotManager::OpenResponse const &response) {
            if (IsSuccess(response.status)) {
              // metadata : gpg::SnapshotMetadata
              metadata = response.data;
            } else {
              // Handle snapshot open error here
            }
          });
    
  2. এরপর, একটি সংরক্ষিত গেম পরিবর্তন তৈরি করুন যাতে কভার ছবির জন্য ব্যবহৃত ছবির ডেটা অন্তর্ভুক্ত থাকে:

    gpg::SnapshotMetadataChange::Builder builder;
    gpg::SnapshotMetadataChange metadata_change =
        builder.SetDescription("CollectAllTheStar savedata")
                 .SetCoverImageFromPngData(pngData).Create();
    
  3. অবশেষে, সংরক্ষিত গেমের পরিবর্তনগুলি কমিট করুন।

    gpg::SnapshotManager::CommitResponse commitResponse =
        service_->Snapshots().CommitBlocking(metadata, metadata_change, SetupSnapshotData());
    

    ডেটা প্যারামিটারে আপনার সংরক্ষণ করা সমস্ত সেভ গেম ডেটা থাকে। পরিবর্তনটিতে অতিরিক্ত সংরক্ষিত গেম মেটাডেটাও থাকে, যেমন খেলার সময় এবং সংরক্ষিত গেমের বিবরণ।

যদি কমিট অপারেশনটি সফলভাবে সম্পন্ন হয়, তাহলে খেলোয়াড়রা সংরক্ষিত গেম নির্বাচন UI-তে সংরক্ষিত গেমটি দেখতে পাবে।