代码之家  ›  专栏  ›  技术社区  ›  Martin Braun

如何跨设备共享已保存的游戏?

  •  6
  • Martin Braun  · 技术社区  · 6 年前

    我在iOS游戏中实现了GameKit,包括保存的游戏功能。

    下面是我如何保存和加载游戏的示例:

    mobscvsavedgamedata.h

    #ifndef MOBSVC_SAVEDGAMEDATA_H
    #define MOBSVC_SAVEDGAMEDATA_H
    
    #import <Foundation/Foundation.h>
    
    @interface MobSvcSavedGameData : NSObject <NSCoding>
    
    @property (readwrite, retain) NSString *data;
    
    +(instancetype)sharedGameData;
    -(void)reset;
    
    @end
    
    
    #endif /* MOBSVC_SAVEDGAMEDATA_H */
    

    #import "MobSvcSavedGameData.h"
    #import <Foundation/Foundation.h>
    
    @interface MobSvcSavedGameData () <NSObject, NSCoding>
    
    @end
    
    @implementation MobSvcSavedGameData
    
    #pragma mark MobSvcSavedGameData implementation
    
    static NSString * const sgDataKey = @"data";
    
    + (instancetype)sharedGameData {
        static id sharedInstance = nil;
    
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            sharedInstance = [[self alloc] init];
        });
    
        return sharedInstance;
    }
    
    - (void)reset
    {
        self.data = nil;
    }
    
    - (void)encodeWithCoder:(NSCoder *)encoder
    {
        [encoder encodeObject:self.data forKey: sgDataKey];
    }
    
    - (nullable instancetype)initWithCoder:(nonnull NSCoder *)decoder {
        self = [self init];
        if (self) {
            self.data = [decoder decodeObjectForKey:sgDataKey];
        }
        return self;
    }
    
    @end
    

    为了简单起见,我上面保存的游戏对象只有一个 NSString 它将被连载和上传如下:

    void MobSvc::uploadSavedGameDataAwait(const char *name, const char *data)
    {
        GKLocalPlayer *mobSvcAccount = [GKLocalPlayer localPlayer];
    
        if(mobSvcAccount.isAuthenticated)
        {
            MobSvcSavedGameData *savedGameData = [[MobSvcSavedGameData alloc] init];
            savedGameData.data = [NSString stringWithUTF8String:data];
            [mobSvcAccount saveGameData:[NSKeyedArchiver archivedDataWithRootObject:savedGameData] withName:[[NSString alloc] initWithUTF8String:name] completionHandler:^(GKSavedGame * _Nullable savedGame __unused, NSError * _Nullable error) {
                if(error == nil)
                {
                    NSLog(@"Successfully uploaded saved game data");
                }
                else
                {
                    NSLog(@"Failed to upload saved game data: %@", error.description);
                }
            }];
        }
    }
    

    这就是我如何在下一次游戏会话中再次下载最新保存的游戏:

    void MobSvc::downloadSavedGameDataAwait(const char *name)
    {
        GKLocalPlayer *mobSvcAccount = [GKLocalPlayer localPlayer];
    
        if(mobSvcAccount.isAuthenticated)
        {
            [mobSvcAccount fetchSavedGamesWithCompletionHandler:^(NSArray<GKSavedGame *> * _Nullable savedGames, NSError * _Nullable error) {
                if(error == nil)
                {
                    GKSavedGame *savedGameToLoad = nil;
                    for(GKSavedGame *savedGame in savedGames) {
                        const char *sname = savedGame.name.UTF8String;
                        if(std::strcmp(sname, name) == 0)
                        {
                            if (savedGameToLoad == nil || savedGameToLoad.modificationDate < savedGame.modificationDate) {
                                savedGameToLoad = savedGame;
                            }
                        }
                    }
                    if(savedGameToLoad != nil) {
                        [savedGameToLoad loadDataWithCompletionHandler:^(NSData * _Nullable data, NSError * _Nullable error) {
                            if(error == nil)
                            {
                                MobSvcSavedGameData *savedGameData = [NSKeyedUnarchiver unarchiveObjectWithData:data];
                                NSLog(@"Successfully downloaded saved game data: %@", [savedGameData.data cStringUsingEncoding:NSUTF8StringEncoding]);
                            }
                            else
                            {
                                NSLog(@"Failed to download saved game data: %@", error.description);
                            }
                        }];
                    }
                }
                else
                {
                    NSLog(@"Failed to prepare saved game data: %@", error.description);
                }
            }];
        }
    }
    

    我通过上传一个随机字符串并在下一个会话中使用相同的 name playerId GKLocalPlayer 实例。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Martin Braun    6 年前

    上面这个问题的例子很好用。用户必须登录iCloud并在Game Center登录时使用相同的apple ID,因为保存的游戏将存储在iCloud中。