Hi guys,
I'm making a mobile game which uses GameCenter multiplayer functionality so this means that we cannot run scripts on the server side and can't have any sort of custom processing on the GameCenter servers. The GameCenter servers only exist for transferring packet data and RPCs to client devices while all processing only exists on the client side.
My current game involves controlling a ball as your main character and moving it around by applying force with screen swipes. So the aim of the game is to capture checkpoints before your opponents. Players can go around collecting powers around the map and using them to hinder opponents from capturing points before them. So right there is no client-server system, it's a peer-to-peer system in which ball position and velocity data is sent over the network while the physics engine takes over on each local device for opponent balls after receiving positional and force data after each swipe.
Now my main issue is regarding contesting when two players seem to touch a power object at the same time. How would one resolve such an issue? Who gets the power and how do you check for it and handle the conflict? Do you send timestamps over the network and compare them? and even if you do that how do you handle it without having devices face much delay?
Would it just make sense to have one of the devices act like a server to resolve such conflicts so it makes network play simpler and more reliable?
Need a solution foir a simple realtime multiplayer mobile game (iOS/Android) using GameCenter Multiplayer functions
You have two main options here, either you call one of your game agents a judge as this might be the one that hosted the game or try some kind of agreement between those two clients.
On the first option it is very simple, you just add some kind of module that verifies every transaction that comes in and send a result back to the client it comed from. This module runs on the hosting client but acts as if nobody runs it so you wont have split case for it. Maybe you could also send your transactions to the network and let the module just perform as if it was a third external server. Then it is very easy, if two would enter the power up at the same time judge decides who gets it (maybe by priority for the hosting player).
Second approach is a bit more tricky and you would maybe have some more computation time and network transits. In this model you wont have a judge but clients could agree who gets the power up first by certain rules. If you gather a conflict, clients would start to talk to each other and try finding a solution. The same approach is used for example in computer networks where only one end could send and the other must hear until it ends to send. They use some kind of random numbers to decide who goes first, i think you could just take some kind of propability into account where that client that has had the judging last time will have a lower chance to get the judging this time too until chance raises some min propability
clients would start to talk to each other and try finding a solution.
Doing competing-capture in a pure peer-to-peer architecture is challenging!
Unfortunately, clients trying to negotiate using more than a single tick state is likely going to be too slow and too complex.
I suggest that you fix your timestep (if you haven't already) and measure time in time steps, not seconds.
Each client then keeps a list of "who, when" for each capturable item.
When you have received the message for step S from all other players, you know who, if anyone, you're competing with.
If someone else captured it before you, give it to them. If someone else captured it after you did, take it. If someone else captured it at the exact same timestep, split the item, or deliver the item to both players.
Separately, you'll have to make sure that every player gets the state for every simulation step. If you simulate 60 steps per second, and send 15 network packets per second, there will be four states for each packet. You should also include state (at least important state, like capture) for a number of previous steps, so that you can tolerate some amount of packet loss. Finally, you have to wait to execute step S until you have received step S-D from all other players, where "D" is the amount of backlog you know each packet includes. This goes to the design of your networking code, as well as the design of your simulation loop, and even your GUI (when you're waiting for a player who is behind, how do you display it to the user?)
You will have to also design your effects to compensate for the latency. For example, if it's a health potion, you would design the animation to look something like:
1) start fading out the potion
2) also start playing a "potion captured" sound
3) when the potion has faded out completely, and the "potion captured" sound has finished playing, start outlining the capturing player in a yellow glow
4) also together with the glow, animate the health bar to go up
This gives you the time of the fading/sound animation to receive information from all other players, and draw the glow/health animation for the right player.
You have two main options here, either you call one of your game agents a judge as this might be the one that hosted the game or try some kind of agreement between those two clients.
On the first option it is very simple, you just add some kind of module that verifies every transaction that comes in and send a result back to the client it comed from. This module runs on the hosting client but acts as if nobody runs it so you wont have split case for it. Maybe you could also send your transactions to the network and let the module just perform as if it was a third external server. Then it is very easy, if two would enter the power up at the same time judge decides who gets it (maybe by priority for the hosting player).
Second approach is a bit more tricky and you would maybe have some more computation time and network transits. In this model you wont have a judge but clients could agree who gets the power up first by certain rules. If you gather a conflict, clients would start to talk to each other and try finding a solution. The same approach is used for example in computer networks where only one end could send and the other must hear until it ends to send. They use some kind of random numbers to decide who goes first, i think you could just take some kind of propability into account where that client that has had the judging last time will have a lower chance to get the judging this time too until chance raises some min propability
Thank a lot man. I'm going to probably just going to go with the Client-Server setup and have the host as one of the players. It seems to be the simplest way to do it. Although it will seem a bit unfair to the side which is not the host, I think the main issue will arise only for really high latencies.
clients would start to talk to each other and try finding a solution.
Doing competing-capture in a pure peer-to-peer architecture is challenging!
Unfortunately, clients trying to negotiate using more than a single tick state is likely going to be too slow and too complex.
I suggest that you fix your timestep (if you haven't already) and measure time in time steps, not seconds.
Each client then keeps a list of "who, when" for each capturable item.
Then, when you think you capture something, you include this fact in the message to the other client, call it at step S.When you have received the message for step S from all other players, you know who, if anyone, you're competing with.
If someone else captured it before you, give it to them. If someone else captured it after you did, take it. If someone else captured it at the exact same timestep, split the item, or deliver the item to both players.
Separately, you'll have to make sure that every player gets the state for every simulation step. If you simulate 60 steps per second, and send 15 network packets per second, there will be four states for each packet. You should also include state (at least important state, like capture) for a number of previous steps, so that you can tolerate some amount of packet loss. Finally, you have to wait to execute step S until you have received step S-D from all other players, where "D" is the amount of backlog you know each packet includes. This goes to the design of your networking code, as well as the design of your simulation loop, and even your GUI (when you're waiting for a player who is behind, how do you display it to the user?)
You will have to also design your effects to compensate for the latency. For example, if it's a health potion, you would design the animation to look something like:
1) start fading out the potion
2) also start playing a "potion captured" sound
3) when the potion has faded out completely, and the "potion captured" sound has finished playing, start outlining the capturing player in a yellow glow
4) also together with the glow, animate the health bar to go up
This gives you the time of the fading/sound animation to receive information from all other players, and draw the glow/health animation for the right player.
Wow your solution is super complex. I think I have to learn a lot of netcoding methods before I can even begin to understand what you said completely. I get the gist of it but not sure if I can implement such things in a short span of time and I need to finish a prototype of my game really soon so I'll probably stick to a 1-tick system and have one of the clients act as a server for now. Will definitely look to upgrade the network code later on if the game is taken well by people. Thank a ton man!