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."#2a2a360,=	.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);