Coping with lag

Started by
7 comments, last by XiotexStudios 18 years, 1 month ago
Hi, I've got the requirement of having two network players interacting with each other using just mouse movement. Each player can see both mouse cursors and each player can paint onto the background. However, with lag rather than seeing a smooth paint what we get is paint splotches which causes issues because player A cannot paint onto areas that Player B has already painted. I wanted to implement some sort of lag predictive stuff but because the motion of the mouse is essentially random I have yet to come up with a good solution... any ideas?
Byron Atkinson-JonesXiotex Studioswww.xiotex.com
Advertisement
Here's my interpretation (I'm no expert)

If whoever painted an area first blocks it off from other players painting there, then it looks like the server will have to make a decision. This may mean that the client won't see where he painted until a small amount of time after, as the server is painting when it gets the information.

A simple solution: fill a packet with the places the client tried to paint over that time inteval. This might involve points, rectangles, circles, intended brush color, etc.

The server gets these, and paints accordingly. If we're only dealing with paintbrush circles, you could probably just send the resultant paint data back to the clients. If other shapes are involved, you might have to send pure image data.

Something like this...
First of all, if you are using TCP, disable your nagle algorithm

(use setsockopt() on your socket with TCP_NODELAY)

Second of all, if you are using TCP, consider using UDP instead if your design allows it, and interpolate between samples. UDP drops packets, so you need to interpolate through dropped samples.

This will give you a good approximation of what the other player drew, but it will not be pixel perfect.

Even in TCP, unless you send samples every single frame (which will probably cause an excessive amount of bandwidth) you will want to interpolate between your samples.. Start with a simple linear interpolation, and if it looks too "blocky" then you may be able to track the mouse's velocity and send that data across with your samples so you can use a cubic spline algorithm for interpolation.

The problem of not being able to draw where other players are drawing is a bit harder.. you cannot defeat latency.. it will always be there. You will run into the situation where 2 players think that an area is free, and both of them draw on it, causing a conflict.

One solution to rhis problem, is to use a client server model. In this model, one player "owns" the canvas, and the other player sends commands describing where he wants to draw. The server (client that "owns" the canvas) simulates the drawing, and sends a command back to the client to tell him where to draw. Using this method, there is no way that one player can draw over another player's lines. However, the client will experience more latency in his draw commands (enough on a moderate connection that it may not seem responsive enough).

The client needs to feel that the game has good responsiveness. To achieve this you need to "hide" the latency. To do this: Use the client server model described above, but allow the local player to see what he draws immediately. When the server responds with the draw commands, the local player can replace his local lines, with those the server has said to draw. If the local player has drawn onto an area that the server says is not free, the client's local line will get erased when the player gets an update from the server. This "hides" the latency, and makes the system seem more responsive.

There is a problem with this scenario, however. Even though both the client and server machines will appear responsive, the server will have a much lower latency then the client, so he will always win if there is ever a conflict about who drew on a certain spot.

To address this, you could queue up the server's commands, and not allow them to be processed until a certain amount of time had elapsed (the average ping time from the client). Like the client machine, you would allow the server's lines to appear immediately. But also like the client machine, You would not draw the "definitive" version of the canvas, until the draw request had been released from your queue, and the actual state of the canvas had been calculated. To do this, the server could have an offscreen "master canvas" (seperate from the canvas he is drawing on) where the lines are drawn, and then update the visible canvas with the new information.

Because the UI of the client and the server behave so similarly now, It would be useful to reuse the same UI (or client) code. The server machine could now have 2 peices: The client (User Interface portion), and the server (portion that processes draw requests and sends out commands telling the clients where to draw). On the server machine, both of these peices could be running in the same app, but instead of the client using the network to communicate with the server, it could use the queue to send commands to the server code.

This way your client code can be identical for both the client machine and the server machine (aside from whether it writes to a queue or the network).

Hope this helps, or at least gets you thinking abount ways to address the problem!



Hi,

Thanks for the responses.

I am using UDP for the protocol.

So far the cursor updates are fine - there aren't that many moves the mouse can make that the eye can't compensate for so in that area we are okay.

The problem is that this is a real-time (well, as much as can be in the context of a game) so the real issue becomes detecting when the client has pressed the mouse button. On top of this when the mouse button is pressed the 'paint' shoots out of the base to the cursor (as in you can track the trajectory) so I can't even compensate for lag time by interpolating between the start and the end points - which would result in paint just popping in the middle of a stream.

I would delay the paint update to match the server and the client but if latency gets really bad then we would be getting less than 10fps which is going to kill it off.. since responsiveness is a priority.

I suspect due to the nature of this game there is no easy solution to this problem.


Byron Atkinson-JonesXiotex Studioswww.xiotex.com
Ok, I'm going to ask a barrage of questions here, but they will help me identify the nature of your needs.

Are players actually drawing things, or would it be more like weapon fire.. where you click the mouse in a spot, and something happens? (i.e. your cursor "firing" paint in a direction.)

Is the amount of paint, or the distance it goes, a function of the time the mouse button is held down? Or is the clicking of the mouse button more of an "event"?

How many players are going to play this game?

Is your game functioning in a lock-step model?


You mentioned the game running at 10fps, and that leads me to believe you are doing some sort of lock-step model. I would ditch the lock step model and make game behavior more asynchronous.

I'm still unsure what you mean by paint splotches. Does the player "draw" with the paint, or is he clicking on points and the paint shoots out 'ala Missile Command?

Is the player trying to hit moving targets with this paint?

If you could give more details about the abstract behavior of your game, I could probably be a lot more helpful.

Also, are you interpolating your mouse movements? I know you say the eye can't tell, but if your mouse position drives where the paint actually renders, then recieving discrete positional samples over the network could cause the paint to make a trail of dots, instead of a continuous stream.

If you send mouse updates 10 times a second, but interpolate between samples, and use the interpolated position as the target for the paint, things should look better.

Doing this tied with "mouse down" "mouse up" events or state information, you should be able to make it work.
Hi,

The missile command analogy works best.

At the moment mouse updates are done at 10ms updates.


I am not familiar with the lock-step model but I can guess and no - I am not doing that.

There could be moving targets with the possibility of both players trying to hit the same target.
Byron Atkinson-JonesXiotex Studioswww.xiotex.com
Lock-step is when you do not continue processing of the game until you have recieved the next packet from the client machine. If you aren't using lock-step, and have a high latency network, but are sending updates at regular intervals and interpolating, your framerate will stay consistent, it's just that the events will register on the remote machine a bit later.

You could hide some of the latency by creating a system to calculate a "game time" (by synchronising clocks), and adding a 60ms delay in the time that the player clicks the button and the paint shoots out. When the player clicks the button the packet can go out saying that the paint will be shot out at a certain game time. That subtracts 60ms of latency fromt he network, and makes it part of the game design (the 60ms could be filled up with a "fire" animation or something to hide it).

Does the paint take time to travel to it's destination? If so you could send a timestamp with each fire packet, and have the remote machine scale the speed of the paint based on the time the paint was fired. That way the end result is consistent (the paint reaches it's destination at the correct time), but the actual travel time of the paint is different.

It sounds like you are going to have to approach the problem from this angle, where you find ways to hide the latency. I would say a predictive model is out of the question (for player input at least).
I agree, the predictive model is out.

The plan I have formed now is that the client machine will act as a dumb terminal with delta information being sent from the server. The client will fire off paint with a syncronised time stamp so that the server can work out its real position and to counter the mid-stream problem it will adjust the speed of the paint spray so that it catches up to where it should be. All other information will be handled by the server so that at all times both players are dealing with the same game rather than two games out of sync with each other.

Any obstacles in the game don't move at a great pace so to compensate deltas will be sent and any lag will be compensated using a lerp.

Hope this works!
Byron Atkinson-JonesXiotex Studioswww.xiotex.com

This topic is closed to new replies.

Advertisement