What would you do in the following scenario:
When implementing a multiplayer game, you use GKMatchmaker to find players.
When the required number of players has connected, you start the match.
Now one of the players receives an incoming call.
What now? If the user takes the call, the application will move to the background, the connection to GameCenter will be lost, right?
What to do with the player and what to do with the match?
I guess you would have to rate that game as lost for the player who has disconnected, and try to go on with the match with the remaining players.
Has anyone come up with a better way of handling this?
The connection to Game Center is not "lost" immediately, i am unsure of the actual timeout period, and would not count on it being any particular period if it is not specified in the docs somewhere. You can always test it for a particular release/version using two connected players.
In our game Tic Tac Toe Twist, when a player disconnects due to timeout or other networking problem, we let the players know who disconnected with a message on screen for five seconds, leave the match we are in, reset the game state and then drop them back to the start game screen.
You could also remove them from your game and recover, if your particular game worked well that way.
Be sure to check out the WWDC 2011 information for updates as to how Game Center will handle this in the future, just in case Apple decides to change things...
Related
First, I will confess that I haven't attempted this in code, so I apologize if this is jumping the gun. I realize that adequate effort and research are a prerequisite to posting good questions. But after reading GameKit and Game Center documentation, as well as iOS Developer Cookbooks, I can't seem to find the right functionality in GameKit and was wondering how I might venture outside it API-wise to solve this problem.
At the simplest level, I would like to implement a time-limited two-player game that does not shut down after one player disconnects, accidentally or maliciously (I currently make no distinction and do not know if I technically can). Essentially, once a match is made, and the two-player match begins, I want the match to continue until one player wins, or match time (say, 10 minutes) expires.
The thing that I want advice on is how to keep a match going when one player disconnects. (Currently, both players disconnecting simultaneously and prematurely leads to immediate termination of the match and no visible result, so no problem there.) How do I set the iOS client to select an action randomly if the user is disconnected? Do I need this program to run on the server, or on both iOS clients? Is it best done in Objective-C to match the iOS applications, or should it be server-side code in some other networking language, like PHP? Are there any APIs that handle this behavior well? On each turn, much like rock-paper-scissors, players have a one-minute time limit to select an action like attack or defend, and if the timer expires without a selection, the computer program randomly selects an action for the player. I'd like to treat a disconnected player the same way: If he or she isn't connected to the match to supply the choice of action, then the computer will do it randomly for him or her at the end of a minute, as if he or she were connected. My purpose for keeping matches online like this is to (a.) ensure that players that disconnect shortly before losing will be assessed a proper loss, (b.) players that stay online in good faith will be assessed their deserved win, and (c.) players that disconnect accidentally or haphazardly can still salvage their match by returning in a timely fashion. I'm sure lots of online games do this, but I just haven't found the proper API or past example for iOS, or two players connecting on their iPhones. Game Center seems to drop the match, or in turn-based games, there isn't some enforceable turn timer (to my knowledge); I didn't see a way to tell who disconnected in the documentation, and I also didn't see some obvious way to keep something online in the case of failure, but with a timer continuing to run. Everything in peer-to-peer seemed to simulate a client-server relationship (one peer the client, one the server), where if the server unit disconnects, the match must end, and if the disconnected player reconnects, the match cannot resume.
In short, I will not object to a code solution, but even some pointers or advice about a framework that supports this behavior will be very much appreciated. Thank you!
Did you consider turn-based matches with timeouts? If a remote player does not respond (times out) control could return to the previous player, which could then conduct intermediate random moves as and while necessary. The application of timeouts for similar scenarios is e.g. discussed in a WWDC 2013 session video.
If you've also implemented a mode where the user can start a game with a computer player locally, then it would be trivial to take any GameCenter game that's timed out and reload it as a local game against a UI.
My assumption would be that once you've implemented a local game with an AI whereby you're saving turns locally each time a player acts. Further, I'm assuming you would use the same data format for both types of games (perhaps changing a bit that says "computer player" instead of "remote player").
When the GC player times out, you code your game to swap out one type of player for another. Register in GC as a win/timeout, and allow the player to continue with the local/AI player.
imagine there is no internet connection when user is playing. The score cannot be submitted to game center. However I save the highscore on the phone using NSUserDefaults too.
So when the user plays next time and is connected to game center should I sync this score he achieved playing "offline"?
Is that a good practice?
Per the Apple Game Center docs, the answer is YES.
Make Sure Your Game Sends Data Again After a Network Failure
When you implement leaderboards or achievements, your game reports a
player’s scores or achievement progress to Game Center. However,
networking is never perfectly reliable. If a networking error occurs,
your game should save the Game Kit object and retry the action again
at a later time. Both the GKScore and GKAchievement classes support
the NSCoding protocol, so your game can archive those objects when it
moves into the background.
Set up a cache that keeps your score data (I use NSUserDefaults) to preserve data between sessions, and every so often (like, each time the user enters the app) test to see if Game Center is reachable, and if so, upload your cached scores. Let me know if you need any code - this post is pretty old, so I won't be surprised if no one ever answers :)
Also per the Apple docs for iOS 5.0 and later network error related issues are handled by a background reporting task so the developer does not need to write anything to handle this if not supporting previous iOS versions.
(from GKScore Class Reference for method reportScoreWithCompletionHandler:)
If the error is a network error and your game is running on iOS 4.3 or earlier, your game should periodically attempt to report the progress until the score is successfully reported. On iOS 5.0 and later, the background reporting task automatically handles network errors on your game’s behalf.
I am not sure what is supposed to happen if no one is logged into Game Center at all though (no network related/ submission issues) when a high score is achieved and then someone logs in later. In that case no GKScore object can even be created because there is no authenticated player and so there is no way to know who actually achieved the score whenever the next person logs into Game Center. Seems handling logged in (even without a network connection temporarily) is best practice but if no one is logged in at all and a high score is gained then it's just tough luck because it is not known who earned it, other than saving it as a device high score. If anyone handles that case then please tell.
Good question.
In my point of view, if a user is offline and is still playing, the score he/she scores should be saved locally. And when he/she again appears online, the offline score shouldn't be submitted online. Because if offline score is submitted, the purpose of making the game online is defeated.
I'm developing a little 1-4 multiplayer jump & run for the iPad and have a problem regarding the synchronization.
The game uses the Game-Center p2p Connection to connect the devices.
Now my problem is,
what data should i send?
-> I have enemies, moving platforms, destructible blocks and Items.
when should I send the data?
Here are my first approaches to sync the PCs (playable characters):
1)
send position (x,y) every frame
--> physics and character don't interact, the character is set to the transmitted position
Problem:
lots of data to send
the PC lags sporadicly
2)
send user input whenever it changes
--> physics and character interact, only the opponents button actions are simulated
Problem:
the latency is not always the same, e.g. the time one button is pressed is not exactly the same on all devices. This means one PC runs longer/shorter on one device.
So what is the best approach to sync a little p2p jump & run game?
Thanks in advance. I appreciate your help.
what data should i send?
Send everything that you would need to know in order to perform the neccesary game logic. Send new locations of enemies, updated health info, etc.
when should I send the data?
Very frequently. You'll want fresh data when you update the screen so that the game appears to be very smooth. Ideally around 30 times per second. Some of the less important data may be able to be sent using the Unreliable method to cut down on network traffic.
i've searched and read many articles and looked at the GKTank apple sample (can't see any specifics about my problem, seems to process events as they occur) but i can't see a sample or tutorial that seems to answer the following
in a multiplayer game over bluetooth/internet (maybe) how do you synchronise player interactions so that the correct game outcome occurs taking into account latency etc ...
for example:
A button is displayed to each player A & B on two separate devices connected via bluetooth
Player A presses the button (Player A is hosting the game and so latency is not an issue)
Player B presses the button just before Player A but his connection to Player A's device has at least a 200ms network latency
problem: the game needs to know Player B pressed first even though Player A's touch request would reach the game code first - i.e. no advantage to the hosting player.
i know the touch event has the timestamp and so i could ensure that the actual time of the press was sent from Player B to the game code... but not sure if thats the right approach and if it is where to go from there..
i expect the answer lies in some game time cycle where touches aren't processed immediately but within a game cycle...
any help on this or pointers to tutorial or specific source code that handles this would be appreciated.
adam
You might want to ask this question on https://gamedev.stackexchange.com/ , as it's a general question about multiplayer lag or latency, and not particularly specific to the iPhone.
You might be able to use timestamps to order the action messages. I think iPhones are synchronized to a date time server maintained by AT&T.
Well I have no actual experience with creating multiplayer games. But as is the case with most game developement questions, I suppose there is no wrong or right, so some logic thinking should do the trick.
Here are some thoughts you might want to consider:
Even if no latency is occuring on Player A's device, you'll have to introduce some to compensate for player B (and vice versa, since from Player B's point of view Player A is late too)
Thus, you'll need to introduce some kind of a "command stack" to buffer input from both players and execute the commands once both Players had the opportunity to contribute their inputs for a given point in gametime
You may want to introduce ping commands to measure the actual latency from time to time
Only one Device (the host) should be measuring the latency and announce it to the client
Based on the measured latency, calculate a time offset (relative to the hosts time) or delay for the commands in the stack (use the latency to convert Player B's timestamps to "local" time)
Keep the delay dynamic if possible, to compensate for varying latency (keep measuring latency throughout the session
If the actual latency peaks beyond the calculated one, commands from Player B may be put onto the stack late - make sure they will be executed anyway (lag may be experienced at this point)
You'll actually need two "layers" - the input layer, which exchanges, buffers and synchronizes the actual input, and a game layer, which receives the delayed commands from the input layer
So far, my 2 cents ;-)
How can the shooting game servers handle the timing, for example when a player shoots another, how do they make sure that both players get the message at the exact same time.
or on most of them u see every detail that a player makes in every second, and both players see the exact same moves on their client? how do the game servers manage to send these moves to all clients (players) at the exact same time?
They don't see them at the exact same time.
The server will determine whether or not the shot hit, and send updates to the clients. The clients will then draw the bullets, blood etc.
There is a timing loop there, but not every event has to be in sync. This is why you see player jumping around under high latency.
From their perspective they are running smoothly, but due to the latency , your client isn't getting updated fast enough.
Most of the packets are sent at a big enough delay that it will make everything look choppy. Everything the client shows will have lag compensation (predicting where projectiles, players, etc. will be in between frames) to make it look like the packets are coming at the same time.