Does anybody know, why this code isn't sending score to GameCenter? Authentication to GC is ok. My leaderboard is 1.
- (void) reportScore: (int64_t) score forLeaderboardID: (NSString*) identifier
{
GKScore *scoreReporter = [[GKScore alloc] initWithLeaderboardIdentifier: identifier];
scoreReporter.value = score;
scoreReporter.context = 0;
NSArray *scores = #[scoreReporter];
[GKScore reportScores:scores withCompletionHandler:^(NSError *error) {
//Do something interesting here.
NSLog(#"sent");
}];
}
I want to touch button and send some value to Game Center.
- (IBAction)sendScoreButton:(id)sender {
[self reportScore:77 forLeaderboardID:#"1"];
}
Related
I am trying to pull the turn based games in which a player is participating in order to populate my tableView.
This is my function to pull their games:
- (void) loadMatchDataWithArray:(NSMutableArray*)currentGames Flag:(bool*)returned
{
NSMutableArray* __block blockGames = currentGames;
bool* __block blockReturn = returned;
[GKTurnBasedMatch loadMatchesWithCompletionHandler:^(NSArray *matches, NSError *error)
{
if (matches)
{
for (int i = 0; i < matches.count; i++)
{
[(GKTurnBasedMatch*)matches[i] loadMatchDataWithCompletionHandler: ^(NSData *matchData, NSError *error)
{
int size = [matchData length];
if (size != 0)
{
Game* game = [NSKeyedUnarchiver unarchiveObjectWithData:matchData];
[blockGames addObject:game];
}
else
{
Game* game = [[Game alloc] init];
[blockGames addObject:game];
game.activePlayer = [GKLocalPlayer localPlayer];
}
*blockReturn = true;
}];
}
}
else
{
*blockReturn = true;
}
}];
}
And this is where I call it:
- (void)viewDidLoad
{
[super viewDidLoad];
[[self tableView]
setBackgroundView:[[UIImageView alloc]
initWithImage:[UIImage imageNamed:#"iPhoneBackground-568h"]]];
bool* returned = false;
[[GKMatchHelper sharedInstance] loadMatchDataWithArray:currentGames Flag:returned];
while (!returned);
[self.tableView reloadData];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
Sadly, this is just giving me a blank black screen and never returns. Is there a way that I can detect when my block comes back and display a loading spinner until then, at which point I would reload the table?
EDIT:
I have revised my code and brought the function inside my MainMenuViewController, and now it builds but never displays the data.
- (void) loadMatchData
{
NSMutableArray* __block blockGames = currentGames;
MainMenuViewController* __weakSelf = self;
[GKTurnBasedMatch loadMatchesWithCompletionHandler:^(NSArray *matches, NSError *error)
{
if (matches)
{
for (int i = 0; i < matches.count; i++)
{
[(GKTurnBasedMatch*)matches[i] loadMatchDataWithCompletionHandler: ^(NSData *matchData, NSError *error)
{
int size = [matchData length];
if (size != 0)
{
Game* game = [NSKeyedUnarchiver unarchiveObjectWithData:matchData];
[blockGames addObject:game];
}
else
{
Game* game = [[Game alloc] init];
[blockGames addObject:game];
game.activePlayer = [GKLocalPlayer localPlayer];
}
[__weakSelf.tableView reloadData];
}];
}
}
[__weakSelf.tableView reloadData];
}];
[__weakSelf.tableView reloadData];
}
And now in my ViewDidLoad I just call:
[self loadMatchData];
Oh dear. Do NOT halt the program execution with "while" loops!
Why not simply call [self.tableView reloadData] at the end of your block?
So,
Remove the last 2 lines in the viewDidLoad method
Replace *blockReturn = true; with [self.tableView reloadData] (you might need to keep a weak reference to 'self' to avoid retain cycles)
Never ever use while (this and that) to wait for an operation to complete. A non-responsive UI is bad and it will cause the users to abandon your app.
I am not knowing anything about gamecentre.I am working on the COCO application
I had gone through gamecenter guide and get able to integrate the game center in my application.
1)
Now the i am able enter the score in the gamecentre through my application.
By doing this:-
- (void) reportScore: (int64_t) score forCategory: (NSString*) category
{
GKScore *scoreReporter = [[[GKScore alloc] initWithCategory:category] autorelease];
scoreReporter.value = score;
[scoreReporter reportScoreWithCompletionHandler: ^(NSError *error)
{
[self callDelegateOnMainThread: #selector(scoreReported:) withArg: NULL error: error];
}];
}
I is working properly uptil yesterday.But now if i tried to update the score it is not updating.Please any one know the reason y the score is not updating in the game center
I had tried to search out but not get anything.
2)I want to send the current latitude & longitude of one player to another.
I came to know that it is possible by GKMATCH
GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease];
request.minPlayers = 1;
request.maxPlayers = 1;
[[GKMatchmaker sharedMatchmaker] findMatchForRequest:request
withCompletionHandler:^(GKMatch *match, NSError *error) {
if (error || !match) {
// handle the error
}
else if (match != nil){
// match found
}}];
/*GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease];
request.minPlayers = 1;
request.maxPlayers = 1;
GKMatchmakerViewController *mmvc = [[GKMatchmakerViewController alloc] initWithMatchRequest:request];
mmvc.matchmakerDelegate = self;
currentMatch.delegate=self;
[self presentModalViewController:mmvc animated:YES];*/
//[mmvc release];
}
- (void)match:(GKMatch *)match player:(NSString *)playerID didChangeState:(GKPlayerConnectionState)state {
switch (state){
case GKPlayerStateConnected:
if (match.expectedPlayerCount == 0) {
// start the match
}
break;
case GKPlayerStateDisconnected:
// remove the player from the match, notify other players, etc
break;
}
}
- (void)matchmakerViewControllerWasCancelled:(GKMatchmakerViewController *)viewController{}
// Matchmaking has failed with an error
- (void)matchmakerViewController:(GKMatchmakerViewController *)viewController didFailWithError:(NSError *)error{
}
// A peer-to-peer match has been found, the game should start
- (void)matchmakerViewController:(GKMatchmakerViewController *)viewController didFindMatch:(GKMatch *)match{
}
// Players have been found for a server-hosted game, the game should start
- (void)matchmakerViewController:(GKMatchmakerViewController *)viewController didFindPlayers:(NSArray *)playerIDs{
}
// An invited player has accepted a hosted invite. Apps should connect through the hosting server and then update the player's connected state (using setConnected:forHostedPlayer:)
- (void)matchmakerViewController:(GKMatchmakerViewController *)viewController didReceiveAcceptFromHostedPlayer:(NSString *)playerID {
}
- (void) sendPosition
{
NSError *error;
NSString* str = #"teststring";
NSData* data = [str dataUsingEncoding:NSUTF8StringEncoding];
// NSData *packet = [NSData dataWithBytes:&msg length:sizeof(PositionPacket)];
[currentMatch sendDataToAllPlayers: data withDataMode: GKMatchSendDataUnreliable error:&error];
if (error != nil)
{
// Handle the erro.r
}
}
But i dont know why but delegate method of GKMatchmakerViewController is not called i had set the delegate but still and even i ama not able to get GKMATCH (here currentMatch).
So due to this
[currentMatch sendDataToAllPlayers: data withDataMode: GKMatchSendDataUnreliable error:&error];
this method is not working.
as CurrentMatch refrence is 0X0.
Please help me out.How do i send and recive data.
M i doing anything wrong?OR is there any thing else to be done.
Please help me.
Thanks
I have built objectives for my game and everything works just fine accept the part of making the objectives not be called any more after any of them is completed.
I know there is a Property of the GKAchievement Class "completed" which is a boolean that returns yes when the Achievement is 100 percent done.
here is the method that called when a Achievement is 100 percent done it passes id which is the Achievement identifier and report the acheeee :
- (void)AchivmentDidAchive:(id)Achivment{
NSString *identifier = Achivment;
NSLog(#"%#",identifier);
self.achivment = [[GKAchievement alloc]initWithIdentifier:identifier];
self.achivment.showsCompletionBanner = YES;
if (!self.achivment.completed) {
self.achivment.percentComplete = 100;
NSLog(#"Reproting!");
[self.achivment reportAchievementWithCompletionHandler: ^(NSError *error)
{
}];
}
else {
NSLog(#"Achivment Completed!");
} }
what I am trying to do here is to set the percent completed to 100 and report it so in the next time ie want get called again.
but it always works... any better idea for how to handle this?
in interface add variable & property:
NSMutableDictionary *earnedAchievementCache;
#property (nonatomic, retain)NSMutableDictionary *earnedAchievementCache;
in .m:
#synthesize earnedAchievementCache;
- (void) submitAchievement: (NSString*) identifier percentComplete: (double) percentComplete
{
if(self.earnedAchievementCache == NULL)
{
[GKAchievement loadAchievementsWithCompletionHandler: ^(NSArray *scores, NSError *error)
{
if(error == NULL)
{
NSMutableDictionary* tempCache= [NSMutableDictionary dictionaryWithCapacity: [scores count]];
for (GKAchievement* score in scores)
{
[tempCache setObject: score forKey: score.identifier];
}
self.earnedAchievementCache= tempCache;
[self submitAchievement: identifier percentComplete: percentComplete];
}
}];
}
else
{
GKAchievement* achievement= [self.earnedAchievementCache objectForKey: identifier];
if(achievement != NULL)
{
if((achievement.percentComplete >= 100.0) || (achievement.percentComplete >= percentComplete))
{
achievement= NULL;
}
achievement.percentComplete= percentComplete;
}
else
{
achievement= [[[GKAchievement alloc] initWithIdentifier: identifier] autorelease];
achievement.percentComplete= percentComplete;
[self.earnedAchievementCache setObject: achievement forKey: achievement.identifier];
}
if(achievement!= NULL)
{
//Submit the Achievement...
if (achievement.percentComplete>=100) {
//show banner
achievement.showsCompletionBanner = YES; //only in IOS 5+
}
[achievement reportAchievementWithCompletionHandler: ^(NSError *error)
{
if (error!=NULL){
NSLog(#"Error!!");
} else NSLog(#"all is well");
}];
}
}
}
in dealloc :
[self.earnedAchievementCache release];
i'm using the cache to not submit scores already submitted / completed
PS: the code is perfect just copy and paste it into your class and it will work
this is what I use in my helper Game Center class:
-(void) reportAchievementWithID:(NSString*) AchievementID {
[GKAchievement loadAchievementsWithCompletionHandler:^(NSArray *achievements, NSError *error) {
if(error) NSLog(#"error");
for (GKAchievement *ach in achievements) {
if([ach.identifier isEqualToString:AchievementID]) { //already submitted
NSLog(#"Already submitted");
return ;
}
}
GKAchievement *achievementToSend = [[GKAchievement alloc] initWithIdentifier:AchievementID];
achievementToSend.percentComplete = 100;
achievementToSend.showsCompletionBanner = YES;
[achievementToSend reportAchievementWithCompletionHandler:NULL];
}];
}
note: I don't use percentages in my achievements, so you'd need to modify things a little bit if you do.
I have it set up so it sends the player's score to the opponents's screen so they can see what their score is, but it never updates the value. Any ideas?
typedef enum
{
kMessageTypeRandomNumber = 0,
kMessageTypeScore,
} MessageType;
typedef struct
{
Message message;
int score;
} MessageScore;
#interface GSMultiplayer : CCLayer <GCHelperDelegate>
{
CCLabelTTF *oppScoreLabel;
uint32_t ourRandom;
BOOL receivedRandom;
}
--------------------------------------------
- (void)sendScore
{
CCLOG(#"Sent Score");
int oppScore = score;
MessageScore message;
message.message.messageType = kMessageTypeScore;
message.score = oppScore;
NSData *data = [NSData dataWithBytes:&message length:sizeof(MessageScore)];
[self sendData:data];
}
- (void)tryStartGame
{
if (isPlayer1 && gameState == kGameStateWaitingForStart)
{
[self setGameState:kGameStateActive];
[self sendGameBegin];
}
[self sendScore];
}
- (void)matchStarted
{
CCLOG(#"Match started");
if (receivedRandom)
{
[self setGameState:kGameStateWaitingForStart];
} else {
[self setGameState:kGameStateWaitingForRandomNumber];
}
[self sendRandomNumber];
[self tryStartGame];
}
- (void)match:(GKMatch *)match didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID
{
Message *message = (Message *) [data bytes];
if (message->messageType == kMessageTypeScore)
{
CCLOG(#"Score Received");
[scoreLabel setString:[NSString stringWithFormat:#"Score: %d", score]];
}
}
}
Also, score is globally delcared from the main "GameScene". I am very new to multiplayer so help is greatly appreciated
Thanks
Keep track of the score yourself and add a layer to display the score.. after player changes scene, send the score to gamecenter?
Is your game using gamekit? If yes, you might wan to look at an example in a game called Infinight.. there is a lite version in the App store.. It has gamecenter multiplayer in it.. Just play it with friends and see how it works.. It also sends score to gamecenter after playing..
in your send data function:
msg.oppScore = score;
NSData *packet = [NSData dataWithBytes:&msg length:sizeof(charInfo)];
[sharedData.myMatch sendDataToAllPlayers: packet withDataMode: GKMatchSendDataUnreliable error:&error];
sharedData.myMatch is suppose to be the GKMatch that you are suppose to reference to when the game starts..
i have integrate game center in my game ...and its working well but i have i new problem now :P
only one score is submit of user .. after that no score submit even its greater then posted score or less...
any idea what i have to exactly doo...
Regards
Haseeb
i use this to submit score......after being sure that the game center is available...
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
GKScore *scoreReporter = [[[GKScore alloc] initWithCategory:gameCenterCategory] autorelease];
int64_t score1 =socre;
scoreReporter.value = score1;
[scoreReporter reportScoreWithCompletionHandler:^(NSError *error) {
if (error != nil) {
NSLog(#"Submit failed");
}
else {
NSLog(#"Score Submited");
}
}];
[pool release];