I'm preparing to launch my first app and want to have multiple leaderboards inside my game. Currently in sandbox mode I can track and log scores into Game Center successfully. Game Center saves my scores (only if it is higher) and seems to be fully functional.
I know through Itunes Connect we have the ability to set up multiple leaderboards and it seems pretty straight forward. I still want to be able to test multiple leaderboards before publishing my game though. Is there a way to do this in sandbox mode? Currently it seems like my scores are only automatically logged into a default leaderboard. Below is the relevant code I'm using to save/access scores. Thanks!
ABGameKitHelper.m
#pragma mark - Leaderboard
-(void) reportScore:(long long)aScore forLeaderboard:(NSString*)leaderboardId
{
GKScore *score = [[GKScore alloc] initWithCategory:leaderboardId];
score.value = aScore;
[score reportScoreWithCompletionHandler:^(NSError *error) {
if (!error)
{
if(![self hasConnectivity])
{
[self cacheScore:score];
}
if (ABGAMEKITHELPER_LOGGING) NSLog(#"ABGameKitHelper: Reported score (%lli) to %# successfully.", score.value, leaderboardId);
}
else
{
[self cacheScore:score];
if (ABGAMEKITHELPER_LOGGING) NSLog(#"ABGameKitHelper: ERROR -> Reporting score (%lli) to %# failed, caching...", score.value, leaderboardId);
}
}];
}
-(void) showLeaderboard:(NSString*)leaderboardId
{
GKLeaderboardViewController *viewController = [GKLeaderboardViewController new];
viewController.leaderboardDelegate = self;
if (leaderboardId)
{
viewController.category = leaderboardId;
CCLOG(#"Going to category already created");
}
[[self topViewController] presentViewController:viewController animated:YES completion:nil];
}
MainScene.m
- (void)gameCenter {
[[ABGameKitHelper sharedHelper] reportScore:1400 forLeaderboard:#"Score"];
[[ABGameKitHelper sharedHelper] showLeaderboard:#"Score"];
}
I'm not sure if I understand your question properly, but I'll try to answer! Game Center does support multiple leaderboards:
-If you want to send a score to specific leaderboard, you just have to call the function [[ABGameKitHelper sharedHelper] reportScore:X forLeaderboard:LEADERBOARD_ID];, where X represents the score you'd like to send, and LEADERBOARD_ID is the ID of the leaderboard you want to send the score to, as specified in iTunes Connect.
-When you have multiple leaderboards, if you don't want to show just one leaderboard, but a list of them all, you should use the GKGameCenterViewController class instead. However, be careful; this ViewController has been added in iOS 6 only, so you must check which version the device is running. I am also using the ABGameKitHelper, so I've made a function to show this kind of view. Here it goes :
ABGameKitHelper.m
- (void) showGameCenter{
if (![[ABGameKitHelper sharedHelper] hasConnectivity]) return;
//Check if device runs on iOS 5
if([[[UIDevice currentDevice]systemVersion]intValue]==5)
{
//If so, we must use the GKLeaderboardViewController
GKLeaderboardViewController *leaderboard = [[GKLeaderboardViewController alloc] init];
if (leaderboard != nil)
{
leaderboard.leaderboardDelegate = self;
[[self topViewController] presentViewController:leaderboard animated:YES completion:nil];
}
}else if ([[[UIDevice currentDevice]systemVersion]intValue]>=6)
{
//if it runs on iOS 6 or higher, we use GKGameCenterViewController
GKGameCenterViewController *gameCenterController = [[GKGameCenterViewController alloc] init];
if (gameCenterController != nil)
{
gameCenterController.gameCenterDelegate = self;
gameCenterController.viewState = GKGameCenterViewControllerStateDefault;
[[self topViewController] presentViewController:gameCenterController animated:YES completion:nil];
}
}
}
And don't forget to add :
- (void) gameCenterViewControllerDidFinish:(GKGameCenterViewController *)gameCenterViewController{
[gameCenterViewController dismissViewControllerAnimated:YES completion:nil];
}
Using this function will allow you to show a nice view containing all your leaderboards and achievements.
Hope this helps!
Related
I'm creating a VR app using the DJI SDK.
I have two UIViews, fpvPreviewView1 and fpvPreviewView2.
How do I create two instances of the same camera? It currently only displays in a single view.
Here's the relevant code.
DJICamera *camera = [self fetchCamera];
if (camera && camera.delegate == self)
[camera setDelegate:nil];
[self resetVideoPreview];
- (DJICamera*) fetchCamera {
if (![DJISDKManager product]) {
return nil;
}
if ([[DJISDKManager product] isKindOfClass:[DJIAircraft class]]) {
return ((DJIAircraft*)[DJISDKManager product]).camera;
}else if ([[DJISDKManager product] isKindOfClass:[DJIHandheld class]]){
return ((DJIHandheld *)[DJISDKManager product]).camera;
}
return nil;
}
[[VideoPreviewer instance] setView:self.fpvPreviewView1];
[[VideoPreviewer instance] setView:self.fpvPreviewView2];
[[VideoPreviewer instance] setView:self.fpvPreviewView1];
[[VideoPreviewer instance] setView:self.fpvPreviewView2];
Time sensitive. Please help!
Thanks!
What you are currently doing is reset the view of the video previewer singleton every time.
What you want to do is create multiple instances of VideoPreviewer and keep a reference to manage properly the resources. VideoPreviewer is heavy.
Try this instead:
self.firstVP = [[VideoPreviewer alloc] init];
[self.firstVP setView:self.fpvPreviewView1];
self.secondVP = [[VideoPreviewer alloc] init];
[self.secondVP setView:self.fpvPreviewView2];
Hope this helps.
I am in the process of making an iOS app (Objective-C), I am nearing the end of my production of the application itself and now I am trying to implements Interstitial Ads. I was before seeing the Blue You are connected to iAd banners before on my app but I do not seem to see them now. My test device (iPhone 5S, iOS 9.2.1) is connected to the internet, so that is not the issue and the account I am using is a free developer account, not a paid one.
Below is code from one of my view controllers (the code is identical on all three of them with regard to iAd), I got the code from Apple's test project and modified it slightly.
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self cycleInterstitial];
// Other non-relavent stuff
}
- (void)like: (UIButton*)button {
// Other non-relavent stuff
NSInteger i = arc4random_uniform(3);
if (i == 2) {
[self presentInterlude];
}
}
- (void)cycleInterstitial {
// Clean up the old interstitial...
NSLog(#"Cycling");
self.inter.delegate = nil;
// and create a new interstitial. We set the delegate so that we can be notified of when
self.inter = [[ADInterstitialAd alloc] init];
self.inter.delegate = self;
}
- (void)presentInterlude {
// If the interstitial managed to load, then we'll present it now.
if (self.inter.loaded) {
NSLog(#"Requesting the ad");
[self requestInterstitialAdPresentation];
}
}
- (void)interstitialAdDidUnload:(ADInterstitialAd *)interstitialAd {
[self cycleInterstitial];
}
- (void)interstitialAd:(ADInterstitialAd *)interstitialAd didFailWithError:(NSError *)error {
[self cycleInterstitial];
}
I know it is not my random number as I removed that previously. Any ideas on why my ads are not showing up? Could it be my code, my non-paid developer account, or is it something else?
I am not trying to display an actual ad I am only trying to get that You are connected to iAd popup to display to confirm that my implementation is working, so it should not be the fact that I am using a non-paid developer account.
I've just implemented a commenting feature in my app. Ideally when someone leaves a comment, I'd like all notified people be able to swipe the push notification and open the app on that post.
I assume you want to open the concerned page directly. There are many ways to go about this, and it depends on how your app is laid out.
If you want to open an inner page upon app launch, you can programmatically trigger the segues that the user would otherwise need to make manually. (this ensures the back/home buttons work as opposed to loading the desired page directly).
Here's an excerpt from one of my own code, your use case may not be the same, but this is all i can do unless you give us more details.
- (BOOL) navigateToRespectiveSectionforPushNot:(NSDictionary*)pushNot
{
id rootVC = self.window.rootViewController;
NSLog(#"ROOT CLASS : %#", [rootVC class]);
if ([rootVC isKindOfClass:[SWRevealViewController class]])
{
NSLog(#"Root Class looking good... mission Navigate!!");
SWRevealViewController *homeVC = (SWRevealViewController*) rootVC;
NSString *category = [[pushNot objectForKey:pushPayloadKeyaps] objectForKey:pushPayloadKeyCategory];
NSString *subCat = [[pushNot objectForKey:pushPayloadKeyaps] objectForKey:pushPayloadKeySubCategory];
NSLog(#"category : %# , subcat : %#",category,subCat);
//The code for the page to which i'm supposed to navigate to is contained in the push notification payload
if ([category isEqualToString:pushCategoryItemChat])
{
[homeVC.rearViewController performSegueWithIdentifier:#"chatPush" sender:nil];
UINavigationController *nc = (UINavigationController*)homeVC.frontViewController;
NSLog(#"FrontView Class : %#",[nc.viewControllers[0] class]);
UITableViewController *tvc = (UITableViewController*)nc.viewControllers[0];
NSDictionary *send = #{chatPushTargetUserId:subCat,chatPushTargetUserName:#"",chatPushTargetUserImage:#""};
[tvc performSegueWithIdentifier:#"seguePushDemoVC" sender:send];
return YES;
}
//communityPush historyPush
else if ([category isEqualToString:pushCategoryItemCommunity])
{
if ([subCat isEqualToString:pushSubCatItemNewRequest])
{
[homeVC.rearViewController performSegueWithIdentifier:#"communityPush" sender:nil];
return YES;
}
else if ([subCat isEqualToString:pushSubCatItemAccepted])
{
[homeVC.rearViewController performSegueWithIdentifier:#"communityPush" sender:nil];
return YES;
}
}
else if ([category isEqualToString:pushCategoryItemHistory])
{
[homeVC.rearViewController performSegueWithIdentifier:#"historyPush" sender:nil];
return YES;
}
}
else
{
UIAlertView *whoa = [[UIAlertView alloc] initWithTitle:#"WHOA!!" message:#" That wasn't supposed to happen. You are not even logged in. Call 911..." delegate:nil cancelButtonTitle:#"mmKay.." otherButtonTitles:nil, nil];
[whoa show];
}
return NO;
}
I hope the code is self explanatory. cheers
I have the game running on the Xcode simulator and also my iPhone. When I hit search they are both put into separate games, instead of one player joining the existing one. It is a turn based game, a player can take their first turn while Game Center is automatching. I am using two separate Game Center accounts with the Sandbox setting on. Any idea what I may be doing wrong? To those who have developed a Game Center supported game, how did you test it? Thanks for the help!
Some code:
- (void)findMatchWithMinPlayers:(int)minPlayers maxPlayers:(int)maxPlayers // view controller calls to find match - nothing if GC unavaiable
viewController:(UIViewController *)viewController {
if (!_enableGameCenter) return;
_matchStarted = NO; // Match not started yet
self.currentMatch = nil;
[viewController dismissViewControllerAnimated:NO completion:nil];
GKMatchRequest *request = [[GKMatchRequest alloc] init]; // Set number of players
request.minPlayers = minPlayers;
request.maxPlayers = maxPlayers;
GKTurnBasedMatchmakerViewController *mmvc = // new instance of the GKMatchmakerViewController with the given request, sets its delegate to the GameKitHelper object, and uses the passed-in view controller to show it on the screen. Shows the user to search for a random player and start a game.
[[GKTurnBasedMatchmakerViewController alloc] initWithMatchRequest:request];
mmvc.turnBasedMatchmakerDelegate = self;
[viewController presentViewController:mmvc animated:YES completion:nil];
}
#pragma mark GKTurnBasedMatchmakerViewControllerDelegate
// A peer-to-peer match has been found, the game should start
- (void)turnBasedMatchmakerViewController:(GKTurnBasedMatchmakerViewController *)viewController didFindMatch:(GKTurnBasedMatch *)match {
[viewController dismissViewControllerAnimated:YES completion:nil];
self.currentMatch = match;
GKTurnBasedParticipant *firstParticipant = [match.participants objectAtIndex:0];
if (firstParticipant.lastTurnDate == NULL) {
// It's a new game!
[delegate enterNewGame:match];
} else {
if ([match.currentParticipant.player isEqual:[GKLocalPlayer localPlayer].playerID]) {
// It's your turn!
[delegate takeTurn:match];
} else {
// It's not your turn, just display the game state.
[delegate layoutMatch:match];
}
}
}
Are you deleting old matches with a partially filled participant list generated during testing prior to starting/joining matches for a new test? You can manually remove old matches from the game center app or use loadMatchesWithCompletionHandler which "loads the turn-based matches involving the local player and creates a match object for each match" at the appropriate time in your code to identify matches for deletion. Refer to Apple's documentation to identify the steps to properly leave, end, and remove a match.
I have a game where on IOS where I want to show the users stance compared to the rest of the players. I can make my own database and input the scores and users that way, but it would be so much easier to use game centers database. Is there some simple function I can use for this?
Thanks in advance!
Yes is possible:
- (IBAction)GameCenter:(id)sender {
GKGameCenterViewController *gameCenterController = [[GKGameCenterViewController alloc] init];
if (gameCenterController != nil){
gameCenterController.gameCenterDelegate = self;
[self presentViewController: gameCenterController animated: YES completion:nil];
}
}
- (void)gameCenterViewControllerDidFinish:(GKGameCenterViewController *)gameCenterViewController
{
[self dismissViewControllerAnimated:YES completion:nil];
}
I suggest to you read this:
http://code.tutsplus.com/tutorials/ios-sdk-game-center-achievements-and-leaderboards-part-1--mobile-5701
Hope this help ;)