07 Pulse
The music is generated live and every note you hear scrolls down a lane toward the hit line. Press on the beat as the tempo creeps up; three misses end the run.
Controls F / J or Left / Right arrows, or tap the left / right half of the screen
985 / 1024 bytes · 39 to spare
The 985 bytes that ship
for(_=');~t(KonJ10` "+_,16^=1,te&&(t),i.st=o.fif.keydown=c.fillTexKo=[],re[0])=>{.value=!S([2]Math."#2a2a360,= .cJnecK=e.crealet e · TAP TO ",RecKStyle=abs[0]-l)<.localStorage.pulse1k,t l i f n=9 s T d=+||S=2,u=,l,i,feiOscillator(fGain(i.frequencyt,f.gain.1,if)e.destinatiJarKlop(l+.1))},y=(T --r||(St d=max(d,s=d)};JkeyJpoinrf=>{if(!f.repeat)if(e=e||new AudioCJxt,S)>40||S>1)(=3,s=T S n=255*random()|i=l+.5~else{=?/j|R/.sK):f.offsetX>a.clientWidth/2,tnd=>t[1]==e!t15~t?s+=(1+(06))*(1+T/8|0T++):y()}},setInrval((for++,l=e?e.currentTime:t/6"#0b0b`32180~i<l+1.1;){=n>>f%8&1;o.push([i,e]u(220*1.2**(3*e+(f>>2&3)ii+=60/(`0+s/2f++}`15143~for( of o)e?":"#ff6bd6`5+`0*e[1],146-130*(-l38!el>+.15ey()~olr(e=>>l-.3"#e9e7df",S?S>1?"PULSESTART":"OUTRETRY":T+"x"^S?64:170"LIVES_r+" _s+" HI_d^20)}^)';G=/[-^-`JK~]/.exec(_);)with(_.split(G))_=join(shift());eval(_)Readable source
// PULSE: hit the notes you hear. F/J, arrows, or tap left/right half.
let au, t = 0, now = 0, nt = 0, i = 0, pat = 90, notes = [], lives = 0, score = 0, combo = 0,
best = +localStorage.pulse1k || 0, dead = 2;
// tone at audio time s
let beep = (f, s, o, g) => {
if (!au || dead) return;
o = au.createOscillator(); g = au.createGain();
o.frequency.value = f; g.gain.value = .1;
o.connect(g).connect(au.destination);
o.start(s); o.stop(s + .1);
};
let miss = () => {
combo = 0;
if (!--lives) dead = 1, t = 0, best = Math.max(best, score), localStorage.pulse1k = best;
};
onkeydown = onpointerdown = e => {
if (e.repeat) return;
au = au || new AudioContext;
if (dead) { if (t > 40 || dead > 1) notes = [], lives = 3, score = combo = 0, dead = 0, pat = Math.random() * 255 | 0, nt = now + .5; }
else {
// pointer: left/right half; key: J or ArrowRight = right
let l = e.key ? /j|R/.test(e.key) : e.offsetX > a.clientWidth / 2,
n = notes.find(n => n[1] == l && !n[2] && Math.abs(n[0] - now) < .15);
if (n) n[2] = 1, score += (1 + (Math.abs(n[0] - now) < .06)) * (1 + combo / 8 | 0), combo++;
else miss();
}
};
setInterval(() => {
t++;
now = au ? au.currentTime : t / 60;
c.fillStyle = '#0b0b10'; c.fillRect(0, 0, 320, 180);
// schedule beats 1.1s ahead (notes enter at the top); tempo rises with score; note lane = sound pitch
while (nt < now + 1.1) {
let l = pat >> i % 8 & 1;
notes.push([nt, l]);
beep(220 * 1.2 ** (l * 3 + (i >> 2 & 3)), nt);
nt += 60 / (100 + score / 2); i++;
}
c.fillStyle = '#2a2a36'; c.fillRect(100, 150, 140, 3);
for (let n of notes) {
c.fillStyle = n[2] ? '#2a2a36' : '#ff6bd6';
c.fillRect(105 + n[1] * 100, 146 - (n[0] - now) * 130, 30, 8);
// passed unhit
if (!n[2] && now > n[0] + .15 && !dead) n[2] = 1, miss();
}
notes = notes.filter(n => n[0] > now - .3);
c.fillStyle = '#e9e7df';
c.fillText(dead ? dead > 1 ? 'PULSE · TAP TO START' : 'OUT · TAP TO RETRY' : combo + 'x', 160, dead ? 64 : 170);
c.fillText('LIVES ' + lives + ' ' + score + ' HI ' + best, 160, 20);
}, 16);