Multiplayer browser game: linear interpolation causing jittering and jumping

Viewed 804

I'm developing a browser multiplayer game, in which each client interpolates (linear) the frames of entities sent by the server. It doesn't look too bad at a high framerate (> 30fps), but starts to jitter at lower framerates (< 30fps) and freezes and jumps and very low framerates (< 10fps). I want to reduce the framerate, and I know it's possible (see Brutal.io which sends updates at 10fps).

This is the basic algorithm which I'm using:

  • The server sends updates at a framerate (say, 10fps)
  • The client renders the game at a framerate (say, 60fps)
  • The client doesn't update the entities on screen to match the server's data straight up: this would look jittery
  • Instead, it uses a linear interpolation function to smooth out the frames between server updates
  • With the example of 10:60fps, the client would render 6 frames in between to create a smooth animation
  • It does this by measuring the delta (difference) between server updates, and also with client render frames
  • It then gets a multiplier by diving client delta by server delta
  • Then, it calls the linear interpolation function, using the screen position, server position, and multiplier, to generate a new screen position

This snippet doesn't contain specific code, but should be good enough to demonstrate the basic overview (see comments in code for info):

var serverDelta = 1; // Setting up a variable to store the time between server updates

// Called when the server sends an update (aiming for 10fps)
function onServerUpdate(message) {
    serverDelta = Date.now() - lastServerFrame;
}

// Called when the client renders (could be as high as 60fps)
var onClientRender() {
    var clientDelta = Date.now() - lastUpdateFrame;

    // Describes the multiplier used for the linear interpolation function
    var lerpMult = clientDelta / serverDelta;
    if (lerpMult > 1) { // Making sure that the screen position doesn't go beyond the server position
        lerpMult = 1;
    }
    lastUpdateFrame = Date.now();

    ...

    // For each entity
    // ($x,$y) is position sent by server, (x,y) is current position on screen
    entity.x = linearInterpolate(entity.x, entity.$x, lerpMult / 2);
    entity.y = linearInterpolate(entity.y, entity.$y, lerpMult / 2);
}

function linearInterpolate(a, b, f) {
    return (a * (1 - f)) + (b * f);
};

As stated above, this creates jitter and jumping in the motion. Is there something I'm doing wrong? How would I make this motion smooth?

1 Answers
Related