I have a "Play Now" button in my app that allows players to be auto-matched with other random players. Maybe I'm missing this somewhere in the docs, but how do I write the code to auto match players?
The Game Center sandbox server has been messed up the last few days, so I'm having a hard time trying different things since I have to guess because the Game Kit docs aren't exactly clear on how to do this. Currently, I have code setup (but untested) to create a match with a friend...
NSArray *playerList = [NSArray arrayWithObject:pid];
GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease];
request.minPlayers = 2;
request.maxPlayers = 4;
request.playersToInvite = playerList;
[[self waitingIndicator] startAnimating];
[[GKMatchmaker sharedMatchmaker] findMatchForRequest:request withCompletionHandler:^(GKMatch *match, NSError *error) {
if (error)
{
//handle error
}
else if (match != nil)
{
self.myMatch = match;
//start match code
}
}];
But how do I auto match two random people looking for a game? My guess, since the docs don't say it, or I'm missing it, is that in order to create an auto match, I simply set the playersToInvite property of the match object to nil? If not, how do I create an auto match?
One other question, while we're on the topic, the Game Kit docs site a few common matchmaking scenarios, one of them being...
A player can also create a network
match using the Game Center
application. When they invite a friend
into a multiplayer game, your
application is launched on both
devices, and each copy of your
application receives an invitation to
join the game.
But I can't figure out how to do this in the Game Center app for testing purposes. How does a user create a network match using the Game Center app? I don't see any buttons for that anywhere in the Game Center app.
Thanks in advance for your wisdom!
Ok, now that the sandbox Game Center server is back up, I was able to confirm that auto-matching works by setting the playersToInvite property to nil, or not setting it all.
Related
I implemented Spotify in my application using CocoaLibSpotify library. I am playing spotify songs from different pages of my app. The problem is, after I played a song then when I try to play another song from another page, it plays the old song for some moments.
This is some code sample.
self.playbackManager = [[SPPlaybackManager alloc] initWithPlaybackSession:[SPSession sharedSession]];
self.playbackManager.playbackSession.playbackDelegate = (id)self;
[self.playbackManager playTrack:track callback:^(NSError *error)
{
if ((error || ([track availability] != SP_TRACK_AVAILABILITY_AVAILABLE)))
{
}
else
{
}
}];
Please help me to fix the issue.
It sounds like you're creating a new playback manager for each page of your app. Don't do this, or they'll overlap one another.
Have only a single playback manager in your whole app - that way, when you play a new track using playTrack:callback:, the new track will replace the old one instantly. Note that you do not set the currentTrack property directly - it's read-only.
I have integrated Game Center (GC) into my game. It works great, except for an annoying message, which can popup in the middle of intense action, requiring 100% of the gamer's attention:
"Could not connect to Game Center server. Cancel/Retry?"
I don't mind about the message, but the information is not so urgent it has to be displayed immediately. I would like to display it after the user has navigated to the main menu or at some other point. Is there a way to achieve it?
Delaying the following login call for game center did the trick for me.
if([GameCenterManager isGameCenterAvailable]){
gameCenterManager = [[GameCenterManager alloc] init];
[gameCenterManager setDelegate:self];
[gameCenterManager authenticateLocalUser];
NSLog(#"Game center logged in");
}
else
NSLog(#"Please login to game center");
I'm using a Game Center leaderboard, which works fine and shows scores as it should do. The only problem is when I simulate a network failure (well, put the phone into airplane mode) it still returns a null error when posting a score. The posting code is -
[scoreReporter reportScoreWithCompletionHandler: ^(NSError *error)
{
[self callDelegateOnMainThread: #selector(scoreReported:) withArg: NULL error: error];
}];
which you would expect to return "unsuccessful" in this case. I've no idea what's going on! Any help appreciated, thanks.
Well, I've sort of worked around it - I've used Apple's Reachability code just to check if the phone can connect, then I do the Game Center stuff. It's weird, but the Game Center doesn't show any error if there's no network when it submits a score, but it does if there is a network & it can't connect to its servers. Unless I'm doing something totally wrong, but it's more-or-less a cut & paste of their own example code.
Waiting for Game Center authentication to complete is a bad idea since it can take a very long time. Moreover, authentication is done not just at game launch but whenever you switch back to a game via fast app switching.
But not waiting for authentication presents problems:
how do you resume a saved game if you don't know who the player is? Ideally, a saved game would be associated with who was playing so you don't have someone resuming another person's game.
how do you resume a game after an app switch back if you don't know who the player is (the player may have changed via the Game Center app)?
a Game Center log in alert might pop up in the middle of an action game (it is not paused)
what if the game is over before authentication completes? What if the initial authentication completes after a few games have been played? What if the initial authentication completes after an app switch or two (which in turn result in more authentications)?
What is a reasonable approach to handle these problems?
Hmm.. i only authenticate at the start of app.. Its set by yourself when you want to authenticate the player.. You might want to save the player alias when the player is first authenticated.. Means:
sharedData.myName = [[GKLocalPlayer localPlayer]alias];
So when the player app switch and stuff, but is not authenticated, you save data under this player alias.. So when the player is finally authenticated, you send the data to GameCenter
Meaning in your checking GameCenter part..
if(!inGame)
{
[[GKLocalPlayer localPlayer] authenticateWithCompletionHandler:^(NSError *error){
if(error == nil){
if(sharedData.myName ==nil)
{
sharedData.myName = [[GKLocalPlayer localPlayer]alias];
}
else if([[GKLocalPlayer localPlayer]alias] == sharedData.myName)
{
[self sendSavedData];
}
else if([[GKLocalPlayer localPlayer]alias] != sharedData.myName)
{
// create new data or look for other saved data which has the same name..
// set sharedData.myName to current player Name..
}
}
enter code here
I can snap a picture with the iPhone programmatically by calling [UIImagePickerController takePicture:], but when I do the iPhone plays a loud recording of a shutter click. When I google for how to turn off the click, I find advice to rename the sound file that the iPhone plays. It seems to me for my app to do that would lead to it being rejected from the App store for accessing system frameworks. Is there a programmatic way to shut off that sound? The nature of my app demands that the camera be silent.
I assume you have solved it since but your app supposed to fail on the Appstore validation as it doesn't comply with iOS Dev License agreement. See below:
Section 3.3.8: Any form of user or device data collection, or image,
picture or voice capture or recording (collectively "Recordings"), and
any form of data, content or information collection, processing,
maintenance, uploading, syncing, storage, transmission, sharing,
disclosure or use performed by, through or in connection with Your
Application must comply with all applicable privacy laws and
regulations as well as any related Program Requirements, including but
not limited to any notice or consent requirements. In particular, a
reasonably conspicuous audio, visual or other indicator must be
displayed to the user as part of the Application to indicate that a
Recording is taking place.
Not sure if you would want to do it...
The sound is there to let someone know a photo is being taken. The idea is to ensure privacy and safety of the public, especially children," something that Japan has already required of their snap-happy citizens
Japan and Korea already have laws that require this sound when taking pictures.
http://abcnews.go.com/Technology/story?id=6750825&page=1
excerpt:
"In Japan and Korea, Segan pointed out, in response to mounting reports of "underskirting," governments have passed laws similar to the one King proposes."
Renaming the sound file wouldn't be using a "private API"; it's simply not possible from within the sandbox (assuming you haven't broken out of the sandbox somehow).
However, on 4.0+, you can use AVCapture to take pictures instead. I'm not sure if AVCaptureStillImageOutput plays a shutter sound; a workaround is to use video frames.
I have to wonder what you mean by "the nature of my app" though. If you're trying to do some sort of live image processing, then video frames are a much better way to go in the first place. If you're trying to take pictures silently with the user's permission, then the user should be able to silence the shutter sound anyway. If you're trying to take pictures without the user's permission, you're probably violating some agreement with Apple.
For what it's worth, I was able to get this to work by using this code in the snapStillImage method of AVCapture framework using AVCaptureStillImageOutput. It works perfectly for me on iOS 8.3 iPhone 5. I have also confirmed that Apple won't reject your app if you use this:
MPVolumeView* volumeView = [[MPVolumeView alloc] init];
//find the volumeSlider
UISlider* volumeViewSlider = nil;
for (UIView *view in [volumeView subviews]){
if ([view.class.description isEqualToString:#"MPVolumeSlider"]){
volumeViewSlider = (UISlider*)view;
break;
}
}
[volumeViewSlider setValue:0.0f animated:YES];
[volumeViewSlider sendActionsForControlEvents:UIControlEventTouchUpInside];
Swift 4:
var volumeView = MPVolumeView()
//find the volumeSlider
var volumeViewSlider: UISlider? = nil
for view: UIView in volumeView.subviews {
if (view.self.description == "MPVolumeSlider") {
volumeViewSlider = view as? UISlider
break
}
}
volumeViewSlider?.setValue(0.0, animated: true)
volumeViewSlider?.sendActions(for: .touchUpInside)