Skip to content

Instantly share code, notes, and snippets.

@timetocode
Created April 23, 2014 22:43
Show Gist options
  • Select an option

  • Save timetocode/11235041 to your computer and use it in GitHub Desktop.

Select an option

Save timetocode/11235041 to your computer and use it in GitHub Desktop.
Entity interpolation
/* Entity Interpolation
this code occurs within the draw loop for an entity
this.x and this.y represent the most recently received server position of
the entity -- though i don't ever intend to use it for drawing
when an update is received (roughly every 50ms in my particular game) this.x and this.y get
pushed into previousState.x and previousState.y
i also continue sloppily onwards to previousPreviousState.x, but I've removed that code
the goal is to have a renderTime which is at least one tick in the past (e.g. if
ticks are 50ms apart, a render time between 50-100ms in the past), and then interpolate between two
already-known position for an entity (.: all entities are drawn slighly in the past, relative
to information we have about them)
pseudo code:
e.g. received tick:260 x:5, y:5, at clientTimestamp: 1000; (known position A)
and then tick:261, x:6, y:5 at clientTimestamp: 1052; (known position B)
now let's say the client is rendering at 60 fps (irrelevant) and we're following the
logic for a hypothetical draw call
current client time: 1096 (hypothetical)
renderTime: 1046 (1096 - 50)
how far from known position A 1000 to known position B 1052 is 1046? (46/52ths of one tick, aka 0.88)
lerp 88% of the way from from position A to position B
done! draw the entity 0.88 of the way between A and B for this particular frame
nextframe:
current client time 1112
renderTime: 1062 (hopefulyl we've received another known position by now, b/c this comes after postion B)
etc!
*/
// actual code
var past = 1000/tickRate
var now = Date.now()
var renderTime = now - past // the exact time (in the past) for which we will create a position, in this case this is ~1 tick ago
// timestamp of a previous position (presumably one tick older than t2)
var t1 = previousState.lastUpdate
// timestamp of most recent position update form server
var t2 = this.lastUpdate
// if we have positional data within this time range
if(entityInterpolationEnabled && renderTime <= t2 && renderTime >= t1) {
// total time from t1 to t2
var total = t2 - t1
// how far between t1 and t2 this entity is as of 'renderTime'
var portion = renderTime - t1
// fractional distance between t1 and t2
var ratio = portion / total
var interpX = math.lerp(previousState.x, this.x, ratio)
var interpY = math.lerp(previousState.y, this.y, ratio)
// draw this entity at the interpolated position
this.drawEntity(interpX, interpY)
} else {
// no interpolation at all, just draw the raw position
this.drawEntity(this.x, this.y)
// in the actual code I attempt some extrapolation when draw is called in a range outside of t1 to t2
// this usually only occurs if the connection or server lag, and renderTime falls into a window for which we have yet
// to receive any data
// tuning the variable 'past' can minimize
}
@czarecoo
Copy link
Copy Markdown

czarecoo commented Jan 5, 2019

still helpful, thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment