Skip to content

Instantly share code, notes, and snippets.

@zzandy
Last active June 23, 2016 11:36
Show Gist options
  • Save zzandy/c5eb5e8f1967f106e98df25093e55002 to your computer and use it in GitHub Desktop.
Save zzandy/c5eb5e8f1967f106e98df25093e55002 to your computer and use it in GitHub Desktop.
fps counting
<!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