הוספת משחקים שמורים למשחק

בעקבות ההוצאה משימוש של API של כניסה באמצעות חשבון Google, אנחנו מסירים את ה-SDK של גרסה 1 למשחקים ב-2026. אחרי פברואר 2025, לא תוכלו לפרסם ב-Google Play כותרים ששולבו לאחרונה עם ערכת ה-SDK של גרסה 1 של משחקים. במקום זאת, מומלץ להשתמש ב-games v2 SDK.
כותרים קיימים עם השילובים הקודמים של המשחקים בגרסה 1 ימשיכו לפעול במשך כמה שנים, אבל מומלץ להעביר אותם לגרסה 2 החל מיוני 2025.
המדריך הזה מיועד לשימוש ב-SDK של Play Games Services v1. עדיין לא זמין SDK ל-C++ עבור Play Games Services v2.

במדריך הזה מוסבר איך לשמור ולטעון את נתוני ההתקדמות של השחקן במשחק באמצעות השירות 'משחקים שמורים' באפליקציה ב-C++‎. אתם יכולים להשתמש בשירות הזה כדי לטעון ולשמור באופן אוטומטי את ההתקדמות של השחקנים במשחק בכל שלב במהלך המשחק. השירות הזה יכול גם לאפשר לשחקנים להפעיל ממשק משתמש כדי לעדכן או לשחזר משחק שמור קיים, או ליצור משחק חדש.

לפני שמתחילים

אם עדיין לא עשיתם זאת, מומלץ לעיין במושגי המשחקים של 'משחקים שמורים'.

לפני שמתחילים לכתוב קוד באמצעות Saved Games API:

פורמטים של נתונים ותאימות בפלטפורמות שונות

נתוני המשחקים השמורים ששומרים בשרתים של Google חייבים להיות בפורמט std::vector<uint8_t>. שירות המשחקים השמורים מטפל בקידוד הנתונים שלכם כדי להבטיח תאימות בפלטפורמות שונות. אפליקציות ל-Android יכולות לקרוא את אותם נתונים כמערך בייטים בלי בעיות תאימות בפלטפורמות שונות.

כשאתם בוחרים פורמט לנתוני המשחקים השמורים, כדאי להימנע משימוש בפורמטים ספציפיים לפלטפורמה. מומלץ מאוד להשתמש בפורמט נתונים, כמו XML או JSON, שיש לו תמיכה חזקה בספריות במספר פלטפורמות.

הפעלת השירות 'משחקים שמורים'

כדי להשתמש בשירות המשחקים השמורים, צריך להפעיל את הגישה אליו. כדי לעשות זאת, צריך להפעיל את EnableSnapshots() כשיוצרים את השירות באמצעות gpg::GameServices::Builder. הפעולה הזו תפעיל את היקפי האימות הנוספים שנדרשים ל'משחקים שמורים' באירוע האימות הבא.

הצגת משחקים שמורים

במשחק שלכם, אתם יכולים לספק אפשרות שמשחקנים יכולים להפעיל כדי לשמור או לשחזר משחקים שמורים. כשהשחקנים יבחרו באפשרות הזו, במשחק אמור להופיע מסך שבו מוצגים חריצי שמירה קיימים, ולאפשר לשחקנים לשמור במיקום מסוים או לטעון ממנו, או ליצור משחק שמירה חדש. כדי לעשות זאת, משתמשים בשיטה הבאה:

  SnapshotManager::ShowSelectUIOperation(...)

ממשק המשתמש לבחירת משחקים שמורים מאפשר לשחקנים ליצור משחק שמורה חדש, להציג פרטים על משחקים שמורים קיימים ולטעון משחקים שמורים קודמים.

  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);
}

בדוגמה הבאה מוסבר איך להציג את ממשק המשתמש של המשחקים השמורים כברירת מחדל, ולטפל בבחירת ממשק המשתמש של השחקן:

  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 גדול מהמספר בפועל של קובצי ה-snapshot שהמשתמש יצר כרגע, ממשק המשתמש של Snapshot שמוגדר כברירת מחדל יציג לשחקנים לחצן ליצירת משחק שמאוחסן ב-Save, במקום לאפשר להם לבחור משחק קיים. (כשהלחצן מוצג, הוא נמצא בחלק התחתון של ממשק המשתמש). כשמשתמש לוחץ על הלחצן הזה, התגובה 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, שירות המשחקים השמורים מזהה אם יש משחק שמור עם שם זהה. התנגשויות נתונים עשויות להתרחש כשהמשחק השמור במכשיר המקומי של השחקן לא מסתנכרן עם הגרסה המרוחקת ששמורה בשרתי Google.

מדיניות ההתנגשויות שציינתם כשפתחתם משחק שמור מאפשרת לשירות המשחקים השמורים לפתור באופן אוטומטי התנגשויות בנתונים. המדיניות יכולה להיות אחת מהאפשרויות הבאות:

המדיניות בנושא התנגשויות תיאור
SnapshotConflictPolicy::MANUAL מציין שהשירות של המשחקים השמורים לא צריך לבצע פעולת פתרון. במקום זאת, המשחק יבצע מיזוג בהתאמה אישית.
SnapshotConflictPolicy::LONGEST_PLAYTIME השירות 'משחקים שמורים' צריך לבחור את המשחק השמור עם ערך זמן המשחק הגבוה ביותר.
SnapshotConflictPolicy::BASE_WINS השירות של המשחקים השמורים צריך לבחור את המשחק הבסיסי השמור.
SnapshotConflictPolicy::REMOTE_WINS השירות 'משחקים שמורים' צריך לבחור את המשחק השמור מרחוק. הגרסה המרוחקת היא גרסה של המשחק השמור שזוהתה באחד מהמכשירים של השחקן, ויש לה חותמת זמן עדכנית יותר מאשר לגרסה הבסיסית.

אם ציינתם מדיניות התנגשויות שאינה GPGSnapshotConflictPolicyManual, שירות המשחקים השמורים ימזג את המשחק השמור ויחזיר את הגרסה המעודכנת דרך הערך 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. קודם פותחים את קובץ snapshot שרוצים לערוך, ובוחרים את הבסיס כדי לוודא שכל ההתנגשויות נפתרות.

    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. לבסוף, מבצעים commit לשינויים שנשמרו במשחק.

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

    הפרמטר data מכיל את כל נתוני המשחק השמורים שאתם מאחסנים. השינוי מכיל גם מטא-נתונים נוספים של משחקים שמורים, כמו משך הזמן שבו שיחקתם במשחק ותיאור של המשחק השמור.

אם פעולת השמירה הושלמה בהצלחה, השחקנים יוכלו לראות את המשחק השמור בממשק המשתמש לבחירת משחקים שמורים.