02 Lanes
Five lanes, nonstop traffic, ever faster. Grab the cyan charge to phase through one obstacle.
Controls Left/Right or A/D to switch lanes; tap left/right half of the screen
999 / 1024 bytes · 25 to spare
The 999 bytes that ship
for(_='l[K+=Jt=VsetUterZl=>Y0)`2,_V=r?^down=?0:e(0,>1?==el(),6*-3for(=[],&&),c.fillText((104+28*.push([Math."#3fe0ff",1K0]K2]let .filZ(Y,(-.5)*d,Style=)"#e9e7df",=K1]localStorage.lanes1kRect( l=random,e=min,fV_i=_o=16r=_nSsdyTh=+||R=Yl<04,lk=(e,f,t)=>{;t--;)Te,f,20])};onkeyonpoinZY{ e=l.keyCode;l.repeat||(t?(f>30||t>1)(yS=f=Vsi=2):i=R(i+(e?(39|68)-(37|65):2*l.offUX>a.clientWidth?1:-1)))},UInZval(()=>{f++,c.UTransform(1,0d*=.9"rgba(1116,.4)",-9,-9,3420`; p=t3:t6,2+f/90`;if(oJ.35*(i-ot||(S=f/10(nJp)>48){nr=R(r+(3*|`-1); V0;t<5;t++)(^<.2:<e(.8,.35+f/9e3))yt,-14,^2:1])} l of y)Jp:"#ff4f6d",-1_,244!tabs(o-)<17>136<162(s=1:s?(sd=5,k(,2)):(V1,fd=1_k(o54,40=h=S>h?0|S:h=`;y=y<180T=T(J,JK3],,,_2--K4]>`)s?"#fff":!=to-54804tt"LANES":"CRASH")+" · TAP TO START"6640|S)+" HI "+h62`}6)';G=/[-^-`YZUVJK]/.exec(_);)with(_.split(G))_=join(shift());eval(_)Readable source
// LANES: dodge the blocks, grab cyan charges to phase through one.
let R = Math.random, M = Math.min;
let t = 0, dead = 2, L = 2, px = 160, s = 2, d = 0, score = 0, charge = 0, shake = 0;
let cells = [], parts = [], au, best = +localStorage.lanes1k || 0;
// clamp to lanes 0..4
let lane = x => x < 0 ? 0 : M(4, x);
// particle burst
let boom = (x, y, n) => { while (n--) parts.push([x, y, R() * 6 - 3, R() * 6 - 3, 20]); };
onkeydown = onpointerdown = e => {
let k = e.keyCode;
if (e.repeat) return;
if (dead) { if (t > 30 || dead > 1) cells = [], score = t = dead = charge = 0, L = 2; }
// keys: arrows / A D; pointer: half of the canvas
else L = lane(L + (k ? (k == 39 | k == 68) - (k == 37 | k == 65) : e.offsetX * 2 > a.clientWidth ? 1 : -1));
};
setInterval(() => {
t++;
c.setTransform(1, 0, 0, 1, (R() - .5) * shake, (R() - .5) * shake);
shake *= .9;
c.fillStyle = 'rgba(11,11,16,.4)';
c.fillRect(-9, -9, 340, 200);
// speed ramps over ~60s; frozen after a crash
let v = dead > 1 ? 3 : dead ? 0 : M(6, 2 + t / 900);
px += (104 + 28 * L - px) * .35;
if (!dead) score = t / 10;
// spawn a row: the safe lane drifts at most 1 lane per row, so a path always exists
if ((d += v) > 48) {
d = 0;
s = lane(s + (R() * 3 | 0) - 1);
// cell kind: 1 block, 2 charge (only in the safe lane)
for (let i = 0; i < 5; i++) if (i == s ? R() < .2 : R() < M(.8, .35 + t / 9000)) cells.push([104 + 28 * i, -14, i == s ? 2 : 1]);
}
for (let q of cells) {
q[1] += v;
c.fillStyle = q[2] > 1 ? '#3fe0ff' : '#ff4f6d';
c.fillRect(q[0] - 12, q[1], 24, 14);
if (!dead && Math.abs(px - q[0]) < 17 && q[1] > 136 && q[1] < 162) {
if (q[2] > 1) charge = 1;
else if (charge) charge = 0, shake = 5, boom(q[0], q[1], 12);
else {
dead = 1; t = 0; shake = 12; boom(px, 154, 40);
localStorage.lanes1k = best = score > best ? score | 0 : best;
}
q[2] = 0;
}
}
cells = cells.filter(q => q[2] && q[1] < 180);
c.fillStyle = '#e9e7df';
parts = parts.filter(q => (q[0] += q[2], q[1] += q[3], c.fillRect(q[0], q[1], 2, 2), --q[4] > 0));
// ship turns white while it holds a charge
c.fillStyle = charge ? '#fff' : '#3fe0ff';
if (dead != 1) c.fillRect(px - 5, 148, 10, 14);
c.fillStyle = '#e9e7df';
if (dead) c.fillText((dead > 1 ? 'LANES' : 'CRASH') + ' · TAP TO START', 160, 64);
c.fillText((score | 0) + ' HI ' + best, 160, 20);
}, 16);