Created
April 23, 2014 22:43
-
-
Save timetocode/11235041 to your computer and use it in GitHub Desktop.
Entity interpolation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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 | |
} |
Thank-you so very much for this code sample, if I may ask under what license is this snippet released under ? Thank-you.
still helpful, thanks
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thank you! This is the guy from youtube who commented ;)