Client.prototype.interpolateEntities = function() {
// Compute render timestamp.
var now = +new Date();
var render_timestamp = now - (1000.0 / server.update_rate);
for (var i in this.entities) {
var entity = this.entities[i];
// No point in interpolating this client's entity.
if (entity.entity_id == this.entity_id) {
continue;
}
// Find the two authoritative positions surrounding the rendering timestamp.
var buffer = entity.position_buffer;
// Drop older positions.
while (buffer.length >= 2 && buffer[1][0] <= render_timestamp) {
buffer.shift();
}
// Interpolate between the two surrounding authoritative positions.
if (buffer.length >= 2 && buffer[0][0] <= render_timestamp && render_timestamp <= buffer[1][0]) {
var x0 = buffer[0][1];
var x1 = buffer[1][1];
var t0 = buffer[0][0];
var t1 = buffer[1][0];
entity.x = x0 + (x1 - x0) * (render_timestamp - t0) / (t1 - t0);
}
}
}
https://www.gabrielgambetta.com/client-side-prediction-live-demo.html
in this article, specifically this line:
entity.x = x0 + (x1 - x0) * (render_timestamp - t0) / (t1 - t0);
He sets incoming positions from the server directly by lerping them rather than setting velocity and letting the clientside gameloop move it along by velocity. Do most games do it like this?
It seems like quake does both(lerping both position and velocity)
https://github.com/id-Software/Quake-III-Arena/blob/dbe4ddb10315479fc00086f08e25d968b4b43c49/code/cgame/cg_predict.c#L250
out->origin[i] = prev->ps.origin[i] + f * (next->ps.origin[i] - prev->ps.origin[i] );
out->velocity[i] = prev->ps.velocity[i] + f * (next->ps.velocity[i] - prev->ps.velocity[i] );
which seems a bit weird to me because wouldnt this be subject to overshooting? Say you want to lerp from tiles x: 1 → x: 2 , well if you just lerp between the two positions and set it directly, it will be just fine. If you lerp positions AND set velocity, I'm presuming somewhere else is doing pos.x += dt * vel.x
, which means you're going to be moving a bit farther.