Members - Reputation: 250
Posted 10 April 2012 - 11:36 AM
I am trying to write something, the closest analogue would be multiplayer asteroids, as in we have ships which can steer left/right and thrust forward. There's no shooting on anything at the moment.
the first version worked like this (everything is UDP) :
- client sends pressed keys info to server every 100 ms
- server calculates physics all the time, sends position info to players every 100 ms
now the problem was, there was choppy movement because client had positions only every 100 ms
next thing I implemented was trying to extrapolate movements based on position, velocity (+angular_velocity) and acceleration.
The problem is: let's say the latency between client and server is 200 ms. Player pressed the "forward" key. Client sends a packet to server (200 ms). Server sends back position packet to client (200 ms). Now, on the server, the player has just started to move, while on client it was moving for 400 ms already. As a result, despite trying to predict the movement, client will have to snap the player back to where it began to accelerate.
How to avoid this? I can't think of a way..
Members - Reputation: 80
Posted 10 April 2012 - 11:59 AM
client sends key pressed packet, waits on server response (a tcp reply saying it has received the packet + any location updates (pop updates into an out vector while it waits for client update)) as it waits for the reply it builds a vector of key presses (if a key has already been pressed it won't add it) and on retrieval of reply sends out the vector..
pretty much, somone starts sending and then people pile up their updates into an outbox which is sent on retrial of packet resieved signal. This will cut out 100ms, all you can really do after that is attempt to improve the smoothing algorithms you are running (that is what I assume the prediction of movement was) maybe have it also do colision detection on the client side, that way in the periods while it waits for updates, it can start the updated movement of collision without needing to receive the update to tell it to, once it does, it updates the location to the servers location.
hope this helps
imo you should make only one person in the network do the calculations (either a server or p2p host) that way there is synchronicity among all of the components in your engine, also, not that it would be an issue, older computers wouldn't need to work as hard so you can use CPU time to optimize graphics display (maybe for a 3D game, not a 2D retro, but you get the idea I hope)
Members - Reputation: 841
Posted 10 April 2012 - 12:06 PM
Now, I'm new to authoritative networking, but I've been reading a lot.
Here's what your problem is.
The client will predict input as permitted, and start moving the player.
After the rtt time of 400ms, the client receives the position of the player from the server, but it is 400 ms old.
In fact, it is only 200ms old relative to the server game state.
Therefore, you need to synch the time between the client and the server.
Once that is acheived, when the client receives a packet, it checks what action it performed at the time stamped on the received packet. Only if there is an error does it need to correct.
Moderators - Reputation: 9562
Posted 10 April 2012 - 08:17 PM
You need to timestamp inputs based on the physics tick at which they happened.
When you send input events to server, and receive back, you should base your simulation on the time stamps in question.
This will allow all players to be in sync at the same time.
Now, to hide the latency of the local player, you can play the local player ahead by the round-trip latency. Thus, while displaying tick T for all remote players, you display the local player at tick T + L, where L is the latency measured in ticks. At the same time, the server is executing approximately tick T+(L/2).
This means that you send commands to the server so they are available just in time for the server to execute tick T+L.
When actions from the player do not match up with what really happens on the server (say, because of actions by other players that the local player has not yet seen,) the server has to detect this and send a correction to the local player, who will correct. This may be smoothly hidden, or it may be a "snap."
Most of the time, the local player will be perfectly predicted, and there will be no need to correct at all.
Members - Reputation: 127
Posted 11 April 2012 - 10:07 PM
Basically when the client moves send the data saying that they have moved. The server can then process this and if they should not move kick them back to their old position. So basically the only reason you would need to "snap" the client to an old position is if some of the data is incorrect.
You do not want the server making all of the calculations! This is a very bad idea! This guarantees that one computer will be dying to crunch data and the other just waiting.
A large key to remember the more data you can cache on each side and the less data you have to send per step the better.
So in this case both need copies of the world, objects, etc and only send the player coords and the "update commands" ex: destory astroid, create, etc.
Also just a heads up most games that look "smooth" run under 100ms ping.
So attempting this with 200ms ping may be like trying to run Crysis on a Windows ME machine.
Network programming is not an easy feat that is for sure!
Best of luck!
Hope some of that triggers an idea.