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

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

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

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

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

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

    פרמטר הנתונים מכיל את כל נתוני המשחק השמורים שאתם מאחסנים. השינוי מכיל גם מטא-נתונים שמורים נוספים של המשחק, כמו שעה הופעל ותיאור של המשחק השמור.

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