يشرح لك هذا الدليل كيفية حفظ وتحميل بيانات مستوى تقدّم اللاعب في اللعبة باستخدام خدمة الألعاب المحفوظة في تطبيق C++. يمكنك استخدام هذه الصفحة خدمة لتحميل وحفظ مستوى تقدم اللاعبين تلقائيًا في أي وقت أثناء اللعب. يمكن لهذه الخدمة أيضًا السماح للّاعبين بتوجيه تشغيل إلى حساب مستخدم. لتحديث أو استعادة لعبة حفظ حالية أو إنشاء لعبة جديدة.
قبل البدء
إذا لم تكن قد فعلت ذلك بالفعل، فقد تجد أنه من المفيد مراجعة مفاهيم ألعاب محفوظة في الألعاب:
قبل بدء الترميز باستخدام واجهة برمجة تطبيقات "الألعاب المحفوظة":
- تثبيت حزمة تطوير البرامج (SDK) الخاصة بـ "ألعاب Play" بلغة C++
- إعداد بيئة تطوير C++
- نزِّل نموذج رمز C++ وراجِعه.
- تفعيل خدمة "الألعاب المحفوظة" في Google Play Console
تنسيقات البيانات والتوافق عبر الأنظمة الأساسية
يجب أن تكون بيانات "الألعاب المحفوظة" التي يتم حفظها في خوادم 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()
) للالتزام بالعناصر المحفوظة
التغييرات في اللعبة.
يوضح المثال التالي كيف يمكنك إنشاء تغيير وتنفيذ لعبة محفوظة.
أولاً، افتح اللقطة التي نريد تعديلها، وتأكد من إزالة جميع التعارضات حله عن طريق اختيار القاعدة.
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 } });
بعد ذلك، أنشئ تغييرًا محفوظًا في اللعبة يتضمن بيانات الصورة المستخدمة في صورة الغلاف:
gpg::SnapshotMetadataChange::Builder builder; gpg::SnapshotMetadataChange metadata_change = builder.SetDescription("CollectAllTheStar savedata") .SetCoverImageFromPngData(pngData).Create();
أخيرًا، اتّبِع تغييرات اللعبة المحفوظة.
gpg::SnapshotManager::CommitResponse commitResponse = service_->Snapshots().CommitBlocking(metadata, metadata_change, SetupSnapshotData());
تحتوي مَعلمة البيانات على جميع بيانات الألعاب المحفوظة التي تخزنها. يشمل التغيير أيضًا بيانات وصفية إضافية محفوظة للعبة، مثل الوقت. التي لعبتها ووصفًا للّعبة المحفوظة.
إذا اكتملت العملية بنجاح، يمكن للّاعبين مشاهدة اللعبة المحفوظة في واجهة مستخدم اختيار الألعاب المحفوظة.