How can I implement & test a multiplayer (turn-based) game using GameKit? Here are the problems I'm facing:
There are no other matches connected to the sandbox, so I don't get any callbacks from macth finder.
Xcode allows only 1 instance of the simulator to run, so how can I have 2 clients connected?
Some suggestions would be great on testing multiplayer GameKit based games.
EDIT:
I have an instance of the app running on device. another on simulator, and I still can't find a match.
// I call this code on both clients after authentication is successful
GKMatchRequest *request = [[GKMatchRequest alloc] init];
request.minPlayers = 2;
request.maxPlayers = 2;
[[GKMatchmaker sharedMatchmaker] findMatchForRequest:request withCompletionHandler:^(GKMatch *match, NSError *error) {
if (error)
{
// Process the error.
NSLog(#"error");
}
else if (match != nil)
{
self.myMatch = match;
match.delegate = self;
if (!self.matchStarted && match.expectedPlayerCount == 0)
{
self.matchStarted = YES;
}
}
}];
You need two devices for testing because the simulator doesn't get any callbacks. Also, if you use auto-match give the Game Center servers a few minutes to update before you search for an auto-match game on the second devices.
Related
I've sent scores to the leaderboard with different test accounts but when I try to see the leaderboard I can only see the score from the account that I'm logged in.
I used this code to send the scores :
- (void)reportScore:(int64_t)score forLeaderboardID:(NSString*)identifier
{
GKScore *scoreReporter = [[GKScore alloc] initWithLeaderboardIdentifier: #"GHS"];
scoreReporter.value = score;
scoreReporter.context = 0;
[GKScore reportScores:#[scoreReporter] withCompletionHandler:^(NSError *error) {
if (error == nil) {
NSLog(#"Score reported successfully!");
} else {
NSLog(#"Unable to report score!");
}
}];
}
This is the code I'm using to show the leaderboard:
- (void)showLeaderboardOnViewController:(UIViewController*)viewController
{
GKGameCenterViewController *gameCenterController = [[GKGameCenterViewController alloc] init];
if (gameCenterController != nil) {
gameCenterController.gameCenterDelegate = self;
gameCenterController.viewState = GKGameCenterViewControllerStateLeaderboards;
gameCenterController.leaderboardIdentifier = _leaderboardIdentifier;
[viewController presentViewController: gameCenterController animated: YES completion:nil];
}
}
Maybe it's because it is sandboxed and stuff? is this normal maybe?
Thanks
I've had this issue before and after much searching it seems to be an error with sandbox accounts. I split my table into highest of all time, highest today and highest friend and in each case other higher scores from my other sandbox accounts were ignored. When I added another one of my accounts as a friend, they started sharing scores just fine.
I used code more or less identical to your own and submitted to the App Store where it was accepted, now it works fine with live accounts.
I am trying to use Game Center to achieve peer to peer communication. But I meet some issues while testing game center. The user authentication is fine, it went through. The problem is matchmaking.
[[GKMatchmaker sharedMatchmaker] findMatchForRequest:request withCompletionHandler:^(GKMatch *match, NSError *error) {
if (error) {
NSLog(#"%#",error.localizedDescription);
}else if (match != nil) {
NSLog(#"good match");
[match setDelegate:self];
}else {
NSLog(#"other error");
}
}];
I want to create own request instead of using GKMatchmakerViewController. But the block code is NOT steady, some time it can work, some time gives me error: cannot connect to server, I don't know it's Game Center server's problem or my code?
Once the above code is working fine, then I set the following handler:
GKMatchRequest *request = [[GKMatchRequest alloc] init];
request.minPlayers = 2;
request.maxPlayers = 2;
request.playersToInvite=[NSArray arrayWithObjects:#"G:****", nil];//yin
request.inviteMessage=#"Welcome to my Game";
request.inviteeResponseHandler=^(NSString *playerID, GKInviteeResponse response) {
if(response==0){
NSLog(#"Accepted....");
}else if(response==1){
NSLog(#"Declined....");
}else if(response==2){
NSLog(#"Failed....");
}else if(response==3){
NSLog(#"3");
}else if(response==4){
NSLog(#"4");
}else if(response==5){
NSLog(#"5");
}else{
NSLog(#"unknown...");
}
};
I tested on different iphone. Once one iphone sends request to other, other can receive the notification, but only other rejects the invitation, then sender iphone can receive, if other accepts, the sender iphone receive nothing. I don't know why this things happened????
And at the receiver iphone side the inviteHandler is working fine. This is wired I tested the whole day, I cannot make it through. I am very brand new with IOS developing. Please help me out of this, appreciate very much!!!!
My Game Center game, upon authentication, for testing I am sending a score to a leaderboard that clearly does not exist in my iTunes Connect page:
// Successful authentication here
[self reportScore:1000 forLeaderboardID:#"blah blah blah blah"];
And here's the method:
-(void)reportScore:(int64_t)score forLeaderboardID:(NSString*)category {
GKScore *scoreReporter = [[GKScore alloc] initWithCategory:category];
scoreReporter.value = score;
scoreReporter.context = 0;
[scoreReporter reportScoreWithCompletionHandler:^(NSError *error) {
if (error == NULL) {
NSLog(#"Score sent successfully");
} else {
NSLog(#"Score submission failed: %#",[error localizedDescription]);
}
}];
}
I am getting
Score sent successfully
Why? I definitely don't have such leaderboard in my game.
Some facts:
My game is of course in iTunes Connect
Game Center seems to work in general. I can make multiplayer matches just fine.
The game has no achievements.
The game is in sandbox mode.
I am authenticated with a test user.
The game in iTunes Connect does have one leaderboard, but definitely not the one I'm referring to in the code above.
Using iOS 7 on an iPhone 5.
Using the sandboxed Gamecenter.
No matter what I do the scores never appear in a leaderboard.
I am using the following code:
- (void)scoreReported: (NSError*) error {
NSLog(#"%#",[error localizedDescription]);
}
- (void)submitScore{
if(self.currentScore > 0)
{
NSLog(#"Score: %lli submitted to leaderboard %#", self.currentScore, self.currentLeaderBoard);
[gameCenterManager reportScore: self.currentScore forCategory: self.currentLeaderBoard];
}
}
And scoreReported doesnt produce an error, yet the score doesnt appear in the leaderboard. I know the category is correct as I use currentLeaderBoard in:
- (void)showLeaderboard {
NSLog(#"leaderboard = %#", self.currentLeaderBoard);
GKLeaderboardViewController *leaderboardController = [[GKLeaderboardViewController alloc] init];
if (leaderboardController != NULL)
{
leaderboardController.category = self.currentLeaderBoard;
//leaderboardController.category = nil;
leaderboardController.timeScope = GKLeaderboardTimeScopeWeek;
leaderboardController.leaderboardDelegate = self;
[self presentModalViewController: leaderboardController animated: YES];
}
}
I have tried the usual
2 different sandbox GC accounts to get the leaderboard working
Even tried 4 different GC accounts each logging in on both the simulator (iOS 6.1) and device (iOS 6.0.1)
Yet still no joy
any suggestions - or is it just that the sandboxed gamecenter is far too buggy!!! (I would raise a bug about sandbox but the apple bug reporting form has a bug in it so that doesnt work either)
Score reporting to Game Center works almost immediately for me, even in sandbox mode.
Here are the few things you can try
Make sure the the Leaderboard identifiers are correct when reporting scores (Should exactly match with "Leaderboard ID"s in iTunesConnect)
Try Deleting the test data under "Manage Game Center" section of iTunesConnect
Delete the application, launch "Game Center" application in your device and goto "Games" tab and remove your app. Reinstall the app and try reporting the score again.
Make sure [gkScore reportScoreWithCompletionHandler:^(NSError *error) doesn't return any error
For those who want to know this what I changed my submitScore method to:
- (void)submitScore {
GKScore * GCscore = [[GKScore alloc] initWithCategory:self.currentLeaderBoard];
GCscore.value = [[NSUserDefaults standardUserDefaults] integerForKey:#"NEWSCORE"];
[GCscore reportScoreWithCompletionHandler:^(NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^(void) {
if (error == NULL) {
NSLog(#"Score Sent");
} else {
NSLog(#"Score Failed, %#",[error localizedDescription]);
}
});
}];
}
and it worked
I'm in sandbox mode implementing game center in my application. The problem comes when I log to gameCenter, in some devices works fine in some others I get a GKErrorCanceled without even get the interface shown.
This devices don't have any user logged in gameCenter so it's not related to have a non sandbox account logged. My code is:
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
//First we try the new iOS6 authentification method for gamekit, if it's not implemented we will use the deprecated one
if ([localPlayer respondsToSelector:#selector(setAuthenticateHandler:)]) {
if (localPlayer.isAuthenticated) {
this->setState(connectionLoged);
this->getDelegate().socialConnectionDidSucceedLogin(*this);
return;
}
else if(!localPlayer.isAuthenticated && localPlayer.authenticateHandler){
this->setState(connectionClosed);
this->getDelegate().socialConnectionDidFailToLogin(*this, std::string("The user already resign to login"));
return;
}
else{
localPlayer.authenticateHandler = ^(UIViewController* viewController, NSError* error){
if (localPlayer.isAuthenticated)
{
_name = [localPlayer.displayName UTF8String];
_userId = [localPlayer.playerID UTF8String];
[GKPlayer loadPlayersForIdentifiers:localPlayer.friends withCompletionHandler:^(NSArray *players, NSError *error) {
for (GKPlayer* player in players) {
if ([player isFriend]) {
NSDictionary* dict =
#{#"displayName" : player.displayName,
#"alias" : player.alias,
#"playerID" : player.playerID};
AttrDictionary* playerInfo = [dict hydraAttrDictionary];
SocialFriend* socialfriend = this->getNewFriendInstance(*playerInfo);
this->addFriend(socialfriend);
delete playerInfo;
}
}
this->getDelegate().socialConnectionDidSucceedLogin(*this);
this->setState(connectionLoged);
}];
}
else if(viewController){
UIViewController* rootViewController = (UIViewController*) [UIApplication sharedApplication].keyWindow.rootViewController ;
[rootViewController presentModalViewController:viewController animated:YES];
}
else{
if(error){
this->getDelegate().socialConnectionDidFailToLogin(*this, std::string([error.description UTF8String]));
}
else{
this->getDelegate().socialConnectionDidFailToLogin(*this, std::string("User cancelled login"));
}
}
};
}
}
//deprecated at IOs 6 authentification method
else
[localPlayer authenticateWithCompletionHandler:^(NSError *error) {
if (localPlayer.isAuthenticated)
{
_name = [localPlayer.displayName UTF8String];
_userId = [localPlayer.playerID UTF8String];
[GKPlayer loadPlayersForIdentifiers:localPlayer.friends withCompletionHandler:^(NSArray *players, NSError *error) {
for (GKPlayer* player in players) {
if ([player isFriend]) {
NSDictionary* dict =
#{#"displayName" : player.displayName,
#"alias" : player.alias,
#"playerID" : player.playerID};
AttrDictionary* playerInfo = [dict hydraAttrDictionary];
SocialFriend* socialfriend = this->getNewFriendInstance(*playerInfo);
this->addFriend(socialfriend);
delete playerInfo;
}
}
this->getDelegate().socialConnectionDidSucceedLogin(*this);
this->setState(connectionLoged);
}];
}
else{
NSString* errorString = [error localizedDescription];
this->getDelegate().socialConnectionDidFailToLogin(*this, std::string([errorString UTF8String]));
this->setState(connectionClosed);
}
}];
I need the code compatible with iOS 6 and iOS 5 so you will see I have the two implementations. For iOS 6 the completion handler returns with an UIViewController null and the error as I say. I'm afraid that in production it happends the same. In the simulator all works fine.
PS- You will find some c++ code, it's because I implement a c++ wrapper for GameCenter as my game is write in cocos2dx...
When someone cancels out of the interface to sign in to game center, it will give you GKErrorCanceled. The third time in a row that they cancel, it will warn them that it will disable game center.
If they do choose to disable game center, then it won't show the interface anymore, and it will just give you GKErrorCanceled instead.
Once game center has been disabled, the only way to sign in is by going into the actual game center app.
The 3 times in a row could be in any app or any combination of apps that use game center, and game center will be disabled for all apps that use game center. The 3 times in a row restarts every time they sign in to game center.
This is for both sandbox and non-sandbox.
This is for both ios 5 and ios 6.