Last active
September 20, 2017 18:29
-
-
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.
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
/** | |
* 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; | |
} | |
} |
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
/** | |
* 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); | |
} |
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
/** | |
* 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