Networking timing difference

Drepple

Member
Hello,

I am working on a multiplayer game in GameMaker. The concept is close to a fighting game and so it's very important both players see the same thing happening at the exact same time. It takes a while for a buffer to be sent to the other player though. A lot of fighting games fix this by having an input delay, where a move is performed say, 2 frames after the input. At the input a buffer is sent to the other player saying the input for a move was given and it will be executed two frames after the input. That player's game will then calculate how long before it has to display the move as well, by subtracting how long ago the message was sent from those two frames.

The problem is that I have no idea how the second player's computer can know how long ago messages were sent. I thought about sending the value of 'get_timer()' to the other player at the beginning of the match and then for every move it will send the time at which it was inputted. Using it's own get_timer() value, the other player's game could then calculate how long after the beginning of the match the input was given in the other player's game and when that would be for itself, but the 'get_timer()' message at the beginning of the match would of course take time to be sent as well and so when the second player receives this message the first player's game will already be hundreds of milliseconds further.

Does anyone have an idea on how I can figure out how long ago a message was sent?
Thanks in advance!
 

The-any-Key

Member
Start by set send_time=get_timer(). Send a message to the client that he respond too. When you get the message back you just get_timer()-send_time. This will give you the ping from you and back.

So when you start an action with your character. Send the action to the client and you wait ping*0.5 before execute it on your screen. Note that this is not a good option for player controlled objects as they can feel like their own controls lag. So make sure something happens when the player click or move. Even if it is just a sound or dummy animation.

Anyway. Make sure you grab ping now and then and get the avarage by last_ping+ping/2. As the ping can flux from 32 to 20000.
 

Drepple

Member
Thanks for the reply, but there's two problems with it. First off the ping can flux, like you said and getting the average every now and then is not exact. Secondly the time it takes for one message to get from player A to player B is rarely the same as the time it takes from player B to player A, so just dividing the total time it takes for the message to go back and forth is also not exact. In most games these things are minor problems, if one at all, and in the end the average will always be correct. For a fighting game however, this is a big problem. They're usually frame perfect, so I'm really looking for a way to know in milliseconds exactly how long ago a message was sent. I appreciate the help though.
 

jaydee

Member
#1) You'll never be sure. It will never be a perfect timer, because it is a variable.

#2) But you can approximate it. During your connection phase, you need to perform a clock synchronisation:

Server sends ping packet -> Client immediately returns ping packet with timestamp -> server immediately returns ping packet with own timestamp.

From the server's perspective, the time at the server is the client's timestamp - ping / 2. This is relatively useless information in this format, except what you can do is store the offset of the client
s timestamp from the server's timestamp. Offset = server time - client time.

Now whenever you execute an event on the client, insert a timestamp at the front of the packet. On the server side, you read the timestamp, and add your offset.
time_since_skill_executed = timestamp + offset - server_time;

And the vice versa on the client side.
(I may have my signs wrong for the offset, I'm quite tired as I'm writing this!)
 

The-any-Key

Member
The idea behind online multiplayer games, is not to make the game be in perfect sync. Because there is no such thing. The idea is to make the player have fun.

Edit:
Else you need to ask the right questions. When is there perfect sync? A console game that have 2 controls is often in perfect sync. So if you try mimic that. You can come close.

So you need to run the game on one common machine that is fast. Ex a nodejs server. So the game itself need to be in nodejs. GM will just work as a common screen.

When you press a button on the controller you need to make make sure that the server get the signal from both controls at the same time. This is not possible because the length of the "cable" will be different for every send.

This means you need to have a synced clock. That show the exact same time on both machines down to the last millisecond, to use as timestamps in the sends. And with common player equipment, that is not possible. As it will take different times to get a synced clock. And then the internal clock of the pc is not accurate enough and will start to drift (around 1 millisecond ever 14 seconds).
 
Last edited:

Drepple

Member
There are indeed no perfect timers, but get_timer() measures time in microseconds, and since the game will round the time to frames in the end (1/60th of a second in my case), there is definitely room for error, as long as the frames will be correct in the end. And no, the idea is in fact to make the game be in perfect sync, because it's a fighting game and in fighting games any difference in frames whatsoever it will become a problem on the level of skilled players. I also won't be using third party servers because it's a peer to peer game and with rollback they work just as well. I appreciate that you're giving me alternatives but in this case I can't accept them. I was only wondering if there's another way to check how long ago a message was sent since ping fluctuates heavily, not why I should be doing that instead. I will look into timing a bit more and try to find out what common fighting games do and work with that, but I do appreciate all the help. Thanks for your suggestions.
 
Top