Skip to content

Instantly share code, notes, and snippets.

@kirbysayshi
Last active September 20, 2017 18:29
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save kirbysayshi/6654845 to your computer and use it in GitHub Desktop.
Save kirbysayshi/6654845 to your computer and use it in GitHub Desktop.
Common code to support a tutorial on fixed-time steps and game loops.
/**
* A verlet integration circle, a simple physics entity.
*/
function Boid(x, y, radius) {
this.cpos = { x: x, y: y }
this.ppos = { x: x, y: y }
this.acel = { x: 0, y: 0 }
this.radius = radius;
}
Boid.prototype.accelerate = function(dt) {
this.cpos.x += this.acel.x * dt * dt * 0.001;
this.cpos.y += this.acel.y * dt * dt * 0.001;
this.acel.x = 0;
this.acel.y = 0;
}
Boid.prototype.inertia = function(dt) {
var x = this.cpos.x*2 - this.ppos.x,
y = this.cpos.y*2 - this.ppos.y;
this.ppos.x = this.cpos.x;
this.ppos.y = this.cpos.y;
this.cpos.x = x;
this.ppos.y = y;
}
// Simple bounds check, just so we can get some continuous movement.
Boid.prototype.boundsCheck = function(maxX, force) {
var dir = this.cpos.x - this.ppos.x;
var dist;
if (this.cpos.x + this.radius > maxX && dir > 0) {
dist = maxX - this.cpos.x + this.radius;
this.ppos.x -= dist;
this.cpos.x -= dist;
this.ppos.x = this.cpos.x + this.cpos.x - this.ppos.x;
} else if (this.cpos.x + this.radius < 0 && dir < 0) {
dist = 0 - this.cpos.x + this.radius;
this.ppos.x -= dist;
this.cpos.x -= dist;
this.ppos.x = this.cpos.x + this.cpos.x - this.ppos.x;
}
}
/**
* Helper function to make a canvas, returning a 2d context.
*/
function ctx(heading) {
var cvs = document.createElement('canvas')
cvs.width = 500;
cvs.height = 50;
var h6 = document.createElement('p');
h6.textContent = heading;
document.body.appendChild(h6);
document.body.appendChild(cvs);
return cvs.getContext('2d');
}
function drawInterpolatedPosition(ctx, boid, ratio) {
var oneMinusRatio = 1 - ratio;
var x = (boid.cpos.x * ratio) + (boid.ppos.x * oneMinusRatio);
var y = (boid.cpos.y * ratio) + (boid.ppos.y * oneMinusRatio);
ctx.fillStyle = 'rgba(0,0,255, 0.3)';
ctx.beginPath();
ctx.arc(x, y, boid.radius, 0, Math.PI*2, false);
ctx.fill();
}
function drawPreviousPosition(ctx, boid) {
ctx.fillStyle = 'rgba(255,0,0, 0.3)';
ctx.beginPath();
ctx.arc(boid.ppos.x, boid.ppos.y, boid.radius, 0, Math.PI*2, false);
ctx.fill();
}
function drawCurrentPosition(ctx, boid) {
ctx.fillStyle = 'rgba(0,255,0, 0.3)';
ctx.beginPath();
ctx.arc(boid.cpos.x, boid.cpos.y, boid.radius, 0, Math.PI*2, false);
ctx.fill();
}
function clearRect(ctx) {
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
}
/**
* Given a target constant delta time, call `logicalStep` enough times
* to consume a larger, irregular delta time, while also providing
* an interpolation ratio to `graphicsStep`, which will be called as
* often as `StepStateInterpolator#update`.
*/
function StepStateInterpolator(targetDT, logicalStep, graphicsStep) {
this.accumulator = 0;
this.accumulatorRatio = 0;
this.logicalStep = logicalStep;
this.graphicsStep = graphicsStep;
this.targetDT = targetDT || 33.3333;
}
StepStateInterpolator.prototype.update = function(dt) {
this.accumulator += dt;
// take the current delta, plus what remains from last time,
// and determine how many logical steps fit.
var steps = Math.floor(this.accumulator / this.targetDT);
// Remove what will be consumed this tick.
if (steps > 0) this.accumulator -= steps * this.targetDT;
this.accumulatorRatio = this.accumulator / this.targetDT;
while(steps > 0) {
this.logicalStep(this.targetDT);
steps--;
}
this.graphicsStep(this.targetDT, this.accumulatorRatio);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment