Skip to content

Instantly share code, notes, and snippets.

@p01
Last active Aug 29, 2015
Embed
What would you like to do?
JS1k 2015 IMPOSSIBLE ROAD

First take on squeezing IMPOSSIBLE ROAD into a JS1k entry

This project was kindly approved by Kevin NG

Test page

// Use the textContent of the shim as noise function
s=document.querySelector('script').textContent.replace(/[\s\n\t\r]/g,'');
// Stretch the noise
R=[];
for(i=0;i<519*16;i++)R[i]=(i/16>4?s.charCodeAt(i/16)%19-9:0)*16*2;
// Smooth the noise
a0=.9;a1=1-a0;
for(j=16;j--;)
for(i=0;i<519*16+16*3;i++)
R[i] = a0*(R[i-1]||0)+a1*(R[i]||0);
// Get deltas
for(i=0;i<R.length;b[i&127]=0)
R[i++] -= R[i%R.length];
onkeydown=onkeyup=function(e){b[e.keyCode]=!!e.type[5];}
vvx=vvy=pos=x=y=px=py=vx=vy=dx=dy=0;
function F(){
//a.style.width = Math.max(360*1.5,innerWidth>>1)+'px';a.style.height = Math.max(180*1.5,innerHeight>>1)+'px';a.style.backgroundColor="#fff";b.style.backgroundColor="#ccc";
a.width|=0;
c.scale(a.width/720,a.height/360);
vx=Math.min(2,Math.max(-2,vx-(b[39]-b[37])/16))
c.globalCompositeOperation='destination-over';
c.fillText(pos>>7,360,20);
// c.fillText(Math.round(dx)+','+Math.round(dy),0,-60);
// c.font='32px arial';
// lastFrame=16*9
// // The road
// //X=x;Y=y;
c.fillStyle='hsla(0,0%,0%,.5)'
c.fillText([px,py].map(function(x){return (" "+Math.round(x)).slice(-4);})+" player",30,80);
c.fillText([ x, y].map(function(x){return (" "+Math.round(x)).slice(-4);})+" road",30,100);
c.fillText([dx,dy].map(function(x){return (" "+Math.round(x)).slice(-4);})+" delta / 2",30,120);
c.fillText([vx,vy].map(function(x){return (" "+Math.round(x*100)).slice(-4);})+" velocity * 100",30,140);
c.translate(360,380);
vvx=vvx*a0+a1*(vx/2);
vvy=vvy*a0+a1*(1+vy/2);
for(i=0;i<999;i++){
posi=pos+i;
u=R[posi%R.length]/2;
posi+=16*3;
v=R[posi%R.length];
posi-=16*3+8
l=96/(i+8);
c.scale(l,l);
c.rotate(Math.atan(v,u)/64);
ll=100;
c.fillStyle= 'hsl(210,90%,'+ll+'%)';
// The vessel
if(i==8) {
// if(pos<lastFrame){
x+=u;
y+=v;
// }
//vx=0;
vx*=.9;
// title = v.toFixed(3)+' // '+vy.toFixed(3);
vy = Math.max(vy-.1, -2);//Math.cos(pos*3.1415/32);
// title += ' --> '+vy.toFixed(3);
px+=vx;
py+=vy;
dx = (x-px)/2;
var inside_x = dx*dx<26*26;
dy = (y-py)/2;
//var below_ish = /*dy<32 && */dy<0;
if(/*inside_x && */dy>0){
// console.log([vy,py,y].map(function(x){ return x.toFixed(3); }).join('\n') +' Forcing the vessel back on track');
py=y;
vy=-v;
}
dy = (y-py)/2;
//ll=inside_x?100:70;
c.arc(dx,dy-16,11,0,7);c.fill();
ll*=.9;
c.fillStyle= 'hsl(210,90%,'+ll+'%)';
c.arc(dx-vx/2,dy-16+vy/2,12,0,7);c.fill();
}
h=Math.min(9,Math.max(3,5+v));
if(i==0){
u-=dx;
v-=dy;
}
c.translate(u+vvx,v-vvy);
k = posi&4?3:7;
k*=4;
c.fillRect(k/2,-h/2,-k,h);
k = 16;
k*=4;
h*=.9;
//ll = i/13+(posi&127?24:48);
u=posi&127;
ll *= (u?.1:.2)+i/999;
c.fillStyle= 'hsl(210,90%,'+ll+'%)';
if(u==0)
c.fillText(posi>>7||'',k/2,-h/2);
c.fillRect(k/2,-h/2,-k,h);
c.scale(1/l,1/l);
}
// next frame
// if(pos<lastFrame)
pos++;
requestAnimationFrame(F);
}
F();
<!doctype html>
<html>
<head>
<title>First prototype of IMPOSSIBLE ROAD for JS1k 2015 by Mathieu 'p01' Henri</title>
<meta charset="utf-8" />
<meta name="author" content="Mathieu 'p01' Henri, @p01"/>
<meta name="viewport" content="width=device-width,initial-scale=1"/>
<style>
html, body { margin: 0; padding: 0; border: 0; }
#c { display: block; } /* kill scrollbars from hell */
</style>
</head>
<body>
<canvas id="c"></canvas>
<script>
var a = document.getElementsByTagName('canvas')[0];
var b = document.body;
var d = function(e){ return function(){ e.parentNode.removeChild(e); }; }(a);
// unprefix some popular vendor prefixed things (but stick to their original name)
var AudioContext =
window.AudioContext ||
window.webkitAudioContext;
window.requestAnimationFrame || (window.requestAnimationFrame =
window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(f){ setTimeout(f, 1000/30); });
(function() {
var originalRAF = window.requestAnimationFrame;
var time = performance.now();
var framesVBLs = new Array(64);
var frameIndex = 0;
var vblsSum = 0;
window.requestAnimationFrame = function(f) {
var now = performance.now();
var vbls = Math.max(1, Math.round((now - time) * 60 / 1000 - .5));
vblsSum += vbls - (framesVBLs[frameIndex]||0);
framesVBLs[frameIndex] = vbls;
frameIndex = ++frameIndex % framesVBLs.length;
var averageFps = Math.round(60/vblsSum*framesVBLs.length);
c.fillText(averageFps+'fps',16,16);
time = now;
originalRAF(f);
};
})();
// fix bug in safari: http://qfox.nl/weblog/218
document.body.clientWidth;
// auto resize (original) canvas. call `onresize(w,h) to limit the size of the canvas
(window.onorientationchange = window.onresize = function(a){
var mw = Infinity;
var mh = Infinity;
var min = Math.min;
return function(w,h){
if (arguments.length === 2) {
mw = w;
mh = h;
}
a.style.width = (a.width = min(mw, innerWidth)) + 'px';
a.style.height = (a.height = min(mh, innerHeight)) + 'px';
};
}(a))();
var c = a.getContext('2d');
</script>
<script>
// p01: "emulation" of having the source code in window._ as expected after compression
_ = document.querySelector('script').textContent.replace(/\s/g, '');
while(_.length<1024)_+=_;
</script>
<script src="impossible_road.js"></script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment