iOS - 整合game center (leader board)

來源:互聯網
上載者:User

iOS - 整合game center (leader board)

最近又一次用到game center裡面的leader board。其實這個事情很簡單,只是很容易忘記。所以就打算寫下來。


iTunes Connect上建立app,然後啟用game center

建立app就省略了,等建立成功後,不需要提交。我們就可以設定game center了。

首先點擊建立的app,找到Game Center,



點擊進入具體的game center設定,可以添加一些項目。很是簡單,基本上都有提示,需要注意的是熱門排行榜id,得搞個獨立的,不要重複。這個id在代碼裡面需要使用。

就這麼簡單的搞幾下,game center就啟用了。



在代碼中引入game center

在xcode的工程裡面開啟game center,




<喎?http://www.bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+1rG907Tyv6q+zdDQo6y40L71aW9zv6q3otS9wLTUvcm1uc/By6Osuse6x6GjPC9wPgo8cD6908/CwLS+zcrHvt/M5bXEtPrC68q1z9bBy6GjPC9wPgo8cD48YnI+CjwvcD4KPHA+PHN0cm9uZz60+sLryrXP1jwvc3Ryb25nPjwvcD4KPHA+ytfPyNTaus/KyrXEtdi3vcztvNPI58/CtPrC66O6zaizo8rHPC9wPgo8cD4tIChCT09MKWFwcGxpY2F0aW9uOihVSUFwcGxpY2F0aW9uICopYXBwbGljYXRpb24gZGlkRmluaXNoTGF1bmNoaW5nV2l0aE9wdGlvbnM6KE5TRGljdGlvbmFyeQogKilsYXVuY2hPcHRpb25zPC9wPgo8cD48cHJlIGNsYXNzPQ=="brush:java;">double ver = [[UIDevice currentDevice].systemVersion doubleValue]; if (ver < 6.0) { [[GKLocalPlayer localPlayer] authenticateWithCompletionHandler:^(NSError *error) { }]; } else { [[GKLocalPlayer localPlayer] setAuthenticateHandler:(^(UIViewController* viewcontroller, NSError *error) { })]; } NSNotificationCenter* ns = [NSNotificationCenter defaultCenter]; [ns addObserver:self selector:@selector(authenticationChanged) name:GKPlayerAuthenticationDidChangeNotificationName object:nil]; 我們給game center增加了一個觀察者,所以就需要在self裡面提供一個函數。這是一個回呼函數,如果使用者沒有登入game center,那麼就會跑到下面,如果登陸了就會跑到上面。

- (void) authenticationChanged{    if ([GKLocalPlayer localPlayer].isAuthenticated) {        NSLog(@"authenticationChanged, authenticated");                            }    else    {                NSLog(@"authenticationChanged, Not authenticated");    }}

接下來就是提交和顯示leader board了。具體的說明蘋果的官網上說的很清楚。我這裡在網上找到一個封裝的原始碼,自己稍微修改了一下。具體代碼看最後面(附)。這裡主要介紹使用流程。先增加一個屬性。

@property (readwrite, retain) PlayerModel * player;
再增加一個函數,如:

- (void) updatePlayer{        if (!self.player || ![self.player.currentPlayerID isEqualToString:[GKLocalPlayer localPlayer].playerID]) {                [self.player release];                self.player = [[PlayerModel alloc] init];    }    [[self player] loadStoredScores];}
這個函數會在authenticationChanged裡面被調到。

- (void) authenticationChanged{    if ([GKLocalPlayer localPlayer].isAuthenticated) {        NSLog(@"authenticationChanged, authenticated");                [self updatePlayer];    }    else    {        NSLog(@"authenticationChanged, Not authenticated");    }}
updatePlayer這個函數比較關鍵。

它支援多使用者,如果是第一次登陸game center,那麼就建立一個對象,如果是換了個使用者登入,那麼就把之前的釋放,然後建立一個新的對象。然後調用loadStoredScore.

loadStoredScore會從本地檔案裡面讀取需要傳送的分數,並且往game center伺服器傳。

上面這段代碼的意思就是app起來後,authenticationChanged被調用了,如果是登入的狀態,那麼就會建立一個PlayerModel對象。如果有需要上傳的資料,那麼就讀取並且嘗試上傳。

其實這是個保護措施,後面會講到為什麼需要這麼做。


接下來就看看如果在遊戲中即時上傳資料。

首先增加一個函數,這個函數就是往伺服器發送資料。self.player submitScore,這個函數會在後面看到。有了這個函數,我們在遊戲或者應用的某個地方可以調用往伺服器發送資料了。LEADERBOARD_DISTANCE的值就是上面connect裡面建立的那個熱門排行榜id。

- (void) storeScore:(NSNumber *)distance{    if (!self.player)        return;        int64_t score64 =  [distance longLongValue];    GKScore * submitScore = [[GKScore alloc] initWithCategory:LEADERBOARD_DISTANCE];    [submitScore setValue:score64];    [self.player submitScore:submitScore];    [submitScore release];}

ok,就這麼簡單。現在就大概講講PlayerModel的原理。因為我們在提交的時候往往會因為網路原因而失敗,特別在中國。所以,PlayerModel裡面就提交了一個機制,如果提交失敗,就把要提交的資料儲存到本地檔案,在合適的時候再嘗試提交。

- (void)submitScore:(GKScore *)score {    if ([GKLocalPlayer localPlayer].authenticated) {        if (!score.value) {            // Unable to validate data.             return;        }                // Store the scores if there is an error.         [score reportScoreWithCompletionHandler:^(NSError *error){            if (!error || (![error code] && ![error domain])) {                // Score submitted correctly. Resubmit others                [self resubmitStoredScores];            } else {                // Store score for next authentication.                 [self storeScore:score];            }        }];    } }
這個函數的主要意思就是,先嘗試提交資料,如果成功,那麼隨便提交一下其他的資料(可能之前提交失敗了)。如果失敗,那麼就把資料儲存下來[self storeScore: score],儲存到一個array,並且寫入本地檔案。這樣就有機會在其他地方再提交一次。完整代碼看後面。

現在就看看如果在app裡面顯示leader board。看下面的代碼gameCenterAuthenticationComplete是我內部使用的一個bool,用來標記使用者是否登入了game center。調用一下這個代碼,就會顯示iOS的game center。

- (void) showGameCenter{    if (gameCenterAuthenticationComplete) {        GKLeaderboardViewController * leaderboardViewController = [[GKLeaderboardViewController alloc] init];        [leaderboardViewController setCategory:LEADERBOARD_DISTANCE];        [leaderboardViewController setLeaderboardDelegate:_viewController];        [self.viewController presentModalViewController:leaderboardViewController  animated:YES];        [leaderboardViewController release];    }}


附,完整PlayerModle代碼:

header file:

#import #import @interface PlayerModel : NSObject {NSLock *writeLock;}@property (readonly, nonatomic) NSString* currentPlayerID;@property (readonly, nonatomic) NSString *storedScoresFilename;@property (readonly, nonatomic) NSMutableArray * storedScores;// Store score for submission at a later time.- (void)storeScore:(GKScore *)score ;// Submit stored scores and remove from stored scores array.- (void)resubmitStoredScores;// Save store on disk. - (void)writeStoredScore;// Load stored scores from disk.- (void)loadStoredScores;// Try to submit score, store on failure.- (void)submitScore:(GKScore *)score ;@end


m file:

#import "PlayerModel.h"@implementation PlayerModel@synthesize storedScores,            currentPlayerID,            storedScoresFilename;- (id)init{    self = [super init];    if (self) {        currentPlayerID = [[NSString stringWithFormat:@"%@", [GKLocalPlayer localPlayer].playerID] retain];        NSString* path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];        storedScoresFilename = [[NSString alloc] initWithFormat:@"%@/%@.storedScores.plist",path, currentPlayerID];        writeLock = [[NSLock alloc] init];    }    return self;}- (void)dealloc{    [storedScores release];    [writeLock release];    [storedScoresFilename release];    [currentPlayerID release];        [super dealloc];}// Attempt to resubmit the scores.- (void)resubmitStoredScores{    if (storedScores) {        // Keeping an index prevents new entries to be added when the network is down         int index = (int)[storedScores count] - 1;        while( index >= 0 ) {            GKScore * score = [storedScores objectAtIndex:index];            [self submitScore:score];            [storedScores removeObjectAtIndex:index];            index--;        }        [self writeStoredScore];    }}// Load stored scores from disk.- (void)loadStoredScores{    NSArray *  unarchivedObj = [NSKeyedUnarchiver unarchiveObjectWithFile:storedScoresFilename];        if (unarchivedObj) {        storedScores = [[NSMutableArray alloc] initWithArray:unarchivedObj];        [self resubmitStoredScores];    } else {        storedScores = [[NSMutableArray alloc] init];    }}// Save stored scores to file. - (void)writeStoredScore{    [writeLock lock];    NSData * archivedScore = [NSKeyedArchiver archivedDataWithRootObject:storedScores];    NSError * error;    [archivedScore writeToFile:storedScoresFilename options:NSDataWritingFileProtectionNone error:&error];    if (error) {        //  Error saving file, handle accordingly     }    [writeLock unlock];}// Store score for submission at a later time.- (void)storeScore:(GKScore *)score {    [storedScores addObject:score];    [self writeStoredScore];}// Attempt to submit a score. On an error store it for a later time.- (void)submitScore:(GKScore *)score {    if ([GKLocalPlayer localPlayer].authenticated) {        if (!score.value) {            // Unable to validate data.             return;        }                // Store the scores if there is an error.         [score reportScoreWithCompletionHandler:^(NSError *error){            if (!error || (![error code] && ![error domain])) {                // Score submitted correctly. Resubmit others                [self resubmitStoredScores];            } else {                // Store score for next authentication.                 [self storeScore:score];            }        }];    } }@end













相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.