Last active
June 23, 2016 11:36
-
-
Save zzandy/c5eb5e8f1967f106e98df25093e55002 to your computer and use it in GitHub Desktop.
fps counting
This file contains hidden or 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
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>---</title> | |
<style type="text/css"> | |
html, body { | |
background-color: #262626; | |
} | |
</style> | |
</head> | |
<body> | |
<script type="text/javascript"> | |
// loop | |
(function(global){ | |
'use strict'; | |
global.makeLoop = function(fixedDelta, fixedUpdate, update){ | |
var acc = 0; | |
return function(delta){ | |
if(delta === undefined || isNaN(delta)){ | |
delta = fixedDelta; | |
} | |
acc += delta; | |
while(acc>=fixedDelta){ | |
fixedUpdate(fixedDelta); | |
acc -= fixedDelta; | |
} | |
update(delta); | |
} | |
} | |
global.loop = function(loopFunction, sheduleFunction){ | |
var then; | |
var iteration = function(){ | |
var now = new Date().getTime(); | |
var delta = now - then; | |
then = now; | |
loopFunction(delta); | |
sheduleFunction(iteration); | |
} | |
iteration(); | |
} | |
}(this)); | |
</script> | |
<script type="text/javascript"> | |
// canvas w/ hex | |
(function(global){ | |
'use strict'; | |
global.fullscreenCanvas = function() { | |
var c = document.createElement('canvas'); | |
var ctx = c.getContext('2d'); | |
ctx.canvas.width = window.innerWidth; | |
ctx.canvas.height = window.innerHeight; | |
ctx.canvas.style.position = 'absolute'; | |
ctx.canvas.style.top = 0; | |
ctx.canvas.style.left = 0; | |
ctx.clear = function(){ | |
ctx.clearRect(-ctx.canvas.width/2, -ctx.canvas.height/2, ctx.canvas.width, ctx.canvas.height); | |
}; | |
var q = 1 / Math.sqrt(3); | |
ctx.getHexPath = function(h){ | |
var dx = q * h / 2; | |
var dy = h / 2; | |
return [2 * dx, 0 | |
,dx, -dy | |
,-dx, -dy | |
,-2 * dx, 0 | |
,-dx, dy | |
,dx, dy]; | |
} | |
ctx.makePath = function(vertices){ | |
this.beginPath(); | |
this.moveTo(vertices[0], vertices[1]); | |
for(var i=2;i<vertices.length;i+=2){ | |
this.lineTo(vertices[i], vertices[i+1]); | |
} | |
this.closePath(); | |
} | |
ctx.pathHex = function (h) { | |
this.makePath(this.getHexPath(h)); | |
}; | |
ctx.fillHex = function (x, y, h) { | |
this.save(); | |
this.translate(x, y); | |
this.pathHex(h); | |
this.fill(); | |
this.restore(); | |
}; | |
ctx.strokeHex = function (x, y, a) { | |
this.save(); | |
this.translate(x, y); | |
this.pathHex(a); | |
this.stroke(); | |
this.restore(); | |
}; | |
ctx.translate(ctx.canvas.width / 2, ctx.canvas.height / 2); | |
document.body.appendChild(c); | |
return ctx; | |
} | |
}(this)); | |
</script> | |
<script type="text/javascript"> | |
// Field | |
(function(global){ | |
"use strict"; | |
function Field(mi, mj, makeCell){ | |
var body = []; | |
for(var i=0;i<mi;++i){ | |
var row = []; | |
for(var j=0;j<mj;++j){ | |
row.push(makeCell(i, j)); | |
} | |
body.push(row); | |
} | |
this.body = body; | |
} | |
Field.prototype.forEach = function(processCell){ | |
for(var i=0;i<this.body.length;++i) | |
for(var j=0;j<this.body[i].length;++j) | |
if(this.body[i][j] !== null) | |
processCell(i, j, this.body[i][j]); | |
} | |
Field.prototype.evolve = function(processCell){ | |
var body = []; | |
for(var i=0;i<this.body.length;++i){ | |
var row = []; | |
for(var j=0;j<this.body[i].length;++j){ | |
var cell = this.body[i][j]; | |
row.push(cell === null ? null : processCell(i, j, cell)); | |
} | |
body.push(row); | |
} | |
this.body = body; | |
} | |
global.Field = Field; | |
}(this)); | |
</script> | |
<script type="text/javascript"> | |
// SuperCell | |
(function(global){ | |
"use strict"; | |
function SuperCell(rank){ | |
if(rank < 1) | |
throw new Error('SuperCell rank cannot be less than 1'); | |
this.rank = rank; | |
} | |
function getDimension(){ | |
return 4 * this.rank + 1; | |
} | |
Object.defineProperty(SuperCell.prototype, 'width', {get: getDimension}); | |
Object.defineProperty(SuperCell.prototype, 'height', {get: getDimension}); | |
SuperCell.prototype.contains = function(i, j){ | |
var r = this.rank; | |
var h2 = r * 2; | |
var a = 8*r + 1; | |
var b = 6*r + 1; | |
var c = 4*r - 1; | |
return j*2 - i + h2-(a + b)/2 <= 0 | |
&& j*2 - i + h2-(a - b)/2 >= 0 | |
&& j*1/2 - i + h2 - (c + b)/4 <= 0 | |
&& j*1/2 - i + h2 - (c - b)/4 >= 0 | |
&& j*-1 - i + h2 + (c + b)/2 >= 0 | |
&& j*-1 - i + h2 + (c - b)/2 <= 0; | |
} | |
global.SuperCell = SuperCell; | |
}(this)); | |
</script> | |
<script type="text/javascript"> | |
var sq32 = Math.sqrt(3) / 2; | |
var tau = 2*Math.PI; | |
function hexToPix(i, j, h) { | |
return [ | |
h * (j) * sq32, | |
-h * (i - j / 2) + h/4 | |
]; | |
} | |
function rnd(){ | |
switch(arguments.length){ | |
case 1: | |
if(arguments[0] instanceof Array) | |
return arguments[0][Math.floor(Math.random()*arguments[0].length)]; | |
else return arguments[0] * Math.random(); | |
case 2: | |
return arguments[0] + Math.random() * (arguments[1] - arguments[0]); | |
case 0: | |
default: | |
return Math.random(); | |
} | |
} | |
function getGenerator(sc, colors){ | |
return function(i,j){ | |
return sc.contains(i, j) | |
? { | |
current: rnd(colors), | |
next: null | |
} | |
: null; | |
} | |
} | |
var colors = ["rgb(255,40,20)", "rgb(153,153,153)", "rgb(238,139,0)", "rgb(139,167,0)", "rgb(0,185,169)", "rgb(94,121,255)", "rgb(207,0,248)"]; | |
var ctx = fullscreenCanvas(); | |
var sc = new SuperCell(5); | |
var fld = new Field(sc.width, sc.height, getGenerator(sc, colors)); | |
var ijorigin = sc.rank*2; | |
function render(i, j, cell){ | |
var s = 30; | |
var pos = hexToPix(i-ijorigin, j-ijorigin, s); | |
var x = pos[0], y = pos[1]; | |
ctx.save(); | |
ctx.translate(x, y) | |
//var outer = ctx.getHexPath(.97*s); | |
//var inner = ctx.getHexPath(.75*s); | |
ctx.fillStyle = cell.current; | |
ctx.beginPath(); | |
ctx.arc(0,0,s/2.5,0,tau); | |
ctx.closePath(); | |
//ctx.makePath(outer); | |
ctx.fill(); | |
ctx.restore(); | |
return; | |
ctx.globalCompositeOperation = 'screen'; | |
var grad = ctx.createLinearGradient(0, s/2, 0, -s/2); | |
grad.addColorStop(1, 'rgba(255,255,255, .3)'); | |
grad.addColorStop(.8, 'rgba(255,255,255,0)'); | |
grad.addColorStop(.6, 'rgba(255,255,255,0)'); | |
grad.addColorStop(.1, 'rgba(255,255,255, .4)'); | |
grad.addColorStop(0, 'rgba(255,255,255,.2)'); | |
ctx.fillStyle = grad; | |
ctx.fill(); | |
grad = ctx.createLinearGradient(0, .7*s/2, 0, .7*-s/2); | |
grad.addColorStop(1, 'rgba(255,255,255, .4)'); | |
grad.addColorStop(0, 'rgba(255,255,255,0)'); | |
ctx.fillStyle = grad; | |
ctx.makePath(inner); | |
ctx.fill(); | |
var l = outer.length; | |
var mode = ['screen', 'screen', 'screen', 'screen', 'multiply', 'multiply']; | |
var tints = [ | |
'rgba(255, 255, 255, .0)', 'rgba(255, 255, 255, .0)', | |
'rgba(255, 255, 255, .2)', 'rgba(255, 255, 255, .4)', | |
'rgba(255, 255, 255, .2)', 'rgba(255, 255, 255, .1)', | |
'rgba(255, 255, 255, .0)', 'rgba(255, 255, 255, .0)', | |
'rgba(0, 0, 0, .1)', 'rgba(0, 0, 0, .3)', | |
'rgba(0, 0, 0, .3)', 'rgba(0, 0, 0, .2)' | |
]; | |
for(var i=0;i<l;i+=2){ | |
grad = ctx.createLinearGradient(outer[i], outer[i+1], inner[(i+3)%l], inner[(i+4)%l]); | |
grad.addColorStop(0, tints[i]); | |
grad.addColorStop(1, tints[i+1]); | |
ctx.fillStyle = grad; | |
ctx.makePath([ | |
outer[i], outer[i+1], outer[(i+2)%l], outer[(i+3)%l], | |
inner[(i+2)%l], inner[(i+3)%l], inner[i], inner[i+1] | |
]); | |
ctx.globalCompositeOperation = mode[i/2]; | |
ctx.fill(); | |
} | |
ctx.restore(); | |
} | |
var colorChange = new Accumulator(2000); | |
var phase = 0; | |
function Accumulator(target){ | |
this.target = target; | |
this.value = 0; | |
} | |
Accumulator.prototype.add = function(value){ | |
this.value += value; | |
if(this.value > this.target) | |
{ | |
this.value -= this.target; | |
return true; | |
} | |
return false; | |
} | |
function MovingAverage(n){ | |
this.samples = new Array(n); | |
this.pointer = 0; | |
} | |
MovingAverage.prototype.addSample = function(sample){ | |
this.samples[this.pointer++] = sample; | |
if(this.pointer>=this.samples.length) | |
this.pointer = 0; | |
} | |
MovingAverage.prototype.average = function(){ | |
var res = this.samples.reduce(function(sumobj, value){return {sum: sumobj.sum + value, count: sumobj.count+1}}, {sum:0,count:0}); | |
return res.sum / res.count; | |
} | |
var fixedFps = new MovingAverage(100); | |
var updateFps = new MovingAverage(100); | |
loop(makeLoop(16, fixedUpdate, update), window.requestAnimationFrame); | |
function fixedUpdate(delta){ | |
fixedFps.addSample(delta); | |
var newTarget = null; | |
if(colorChange.add(delta)) { | |
newTarget = rnd(colors); | |
} | |
fld.evolve(function(i, j, cell){ | |
if(cell.next && cell.next.in < delta) | |
cell.current = cell.next.value; | |
if(newTarget) { | |
cell.next = { | |
value : newTarget, | |
in: 20*(i+j) * rnd(.8, 1.2) | |
}; | |
} | |
else if(cell.next){ | |
cell.next.in -= delta; | |
} | |
return cell; | |
}); | |
} | |
function reportfps(){ | |
console.log('fixed: '+1000/fixedFps.average()+'; update: '+1000/updateFps.average()) | |
} | |
function update(delta){ | |
updateFps.addSample(delta); | |
ctx.clear(); | |
fld.forEach(render); | |
} | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment