hypeorcode
Network offOpen alone (new tab)

Run details

Model
claude-sonnet-5-5
Route
Claude Code CLI
Reasoning
provider default
Date
2 Oct 2026
Time
53 s
Size
13 kB
Tokens
4 in, 8,273 out
List price
$0.083 ($2 in / $10 out per M)
Paid
Not billed per run (CLI plan)

Raw files: output · meta.json

Exact prompt

Make a Breakout game I can play right now with the keyboard or the mouse. Give it several levels, a score and some juice.

It must be one complete, self-contained HTML file: inline all CSS and JavaScript, and make no network requests of any kind (no CDNs, web fonts or remote images). Save it as index.html in the current directory, then stop. Do not ask questions.

Source

13 kB 312 lines Raw

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Breakout</title>
<style>
  html,body{margin:0;height:100%;background:#07070f;color:#cfe;font-family:ui-monospace,Menlo,Consolas,monospace;overflow:hidden}
  body{display:flex;align-items:center;justify-content:center}
  canvas{background:#0b0b1a;max-width:100vw;max-height:100vh;box-shadow:0 0 40px #0ff3;border-radius:6px;cursor:none;touch-action:none}
</style>
</head>
<body>
<canvas id="c" width="800" height="600"></canvas>
<script>
(()=>{
const cv=document.getElementById('c'),ctx=cv.getContext('2d');
const W=800,H=600;
const PH=14,BR=7;
const COLS=10,BW=68,BH=24,BGAP=6,BX0=(W-(COLS*(BW+BGAP)-BGAP))/2,BY0=70;
const hues=[0,25,50,120,180,220,280,320];

// ---- audio (synthesized, no network) ----
let ac=null;
function beep(f,d,type='square',vol=.06,slide=0){
  try{
    ac=ac||new (window.AudioContext||window.webkitAudioContext)();
    const o=ac.createOscillator(),g=ac.createGain();
    o.type=type;o.frequency.value=f;
    if(slide)o.frequency.exponentialRampToValueAtTime(Math.max(30,f+slide),ac.currentTime+d);
    g.gain.value=vol;g.gain.exponentialRampToValueAtTime(.0001,ac.currentTime+d);
    o.connect(g);g.connect(ac.destination);o.start();o.stop(ac.currentTime+d);
  }catch(e){}
}

// ---- levels: strings, '.' empty, digit = hits (1-3), '#' = unbreakable ----
const LEVELS=[
 ["..........","1111111111","1111111111","1111111111","1111111111"],
 ["1.1.1.1.1.",".1.1.1.1.1","1.1.1.1.1.","2222222222","..........","1111111111"],
 ["....11....","...1221...","..123321..",".12333321.","..123321..","...1221...","....11...."],
 ["#.......#.","2222222222","1.1.1.1.1.",".2.2.2.2.2","3333333333","#........#"],
 ["3333333333","2#2222222#","1.1.##.1.1","2#2222222#","3333333333","1111111111"],
 ["#2#2#2#2#2","2#3#3#3#3#","#3#1#1#1#3","3#1#.#.#1#","1#1#1#1#1#","3333333333"]
];

let state='title',level=0,score=0,lives=3,best=+(localStorage.getItem('bo_best')||0);
let bricks=[],balls=[],parts=[],pops=[],powers=[],trail=[];
let paddle={x:W/2,w:100,tw:100},shake=0,flash=0,combo=0,stateT=0,bannerT=0,sticky=0,slow=0;
let keys={},mouseX=null,usingMouse=false,stars=[];
for(let i=0;i<70;i++)stars.push({x:Math.random()*W,y:Math.random()*H,z:Math.random()*.8+.2});

function buildLevel(n){
  bricks=[];
  const L=LEVELS[n%LEVELS.length],loop=Math.floor(n/LEVELS.length);
  L.forEach((row,r)=>{
    [...row].forEach((ch,c)=>{
      if(ch==='.')return;
      const u=ch==='#';
      let hp=u?99:Math.min(3,+ch+(loop>0&&!u&&Math.random()<.3?1:0));
      bricks.push({x:BX0+c*(BW+BGAP),y:BY0+r*(BH+BGAP),hp,max:hp,u,hue:hues[(r+c)%hues.length],hit:0});
    });
  });
}
function speed(){return 5.2+level*.45+Math.min(combo,10)*.05}
function resetBall(){
  balls=[{x:paddle.x,y:H-50-BR,vx:0,vy:0,stuck:true}];trail=[];combo=0;
}
function startLevel(n){
  level=n;buildLevel(n);powers=[];paddle.tw=paddle.w=100;sticky=0;slow=0;resetBall();
  bannerT=120;
}
function newGame(){score=0;lives=3;startLevel(0);state='play';beep(440,.2,'triangle',.08,400)}

function burst(x,y,hue,n=14,sp=4){
  for(let i=0;i<n;i++){
    const a=Math.random()*6.283,s=Math.random()*sp+1;
    parts.push({x,y,vx:Math.cos(a)*s,vy:Math.sin(a)*s,life:1,hue,sz:Math.random()*3+1.5});
  }
}
function pop(x,y,t,hue=50){pops.push({x,y,t,life:1,hue})}

function launch(){
  const b=balls.find(b=>b.stuck);if(!b)return;
  const a=-Math.PI/2+(Math.random()-.5)*.5,s=speed();
  b.vx=Math.cos(a)*s;b.vy=Math.sin(a)*s;b.stuck=false;beep(520,.08,'square',.05,300);
}
function action(){
  if(state==='title'||state==='over'||state==='win')newGame();
  else if(state==='play')launch();
  else if(state==='pause')state='play';
}

addEventListener('keydown',e=>{
  if(['ArrowLeft','ArrowRight',' ','ArrowUp','ArrowDown'].includes(e.key))e.preventDefault();
  keys[e.key.toLowerCase()]=true;usingMouse=false;
  if(e.key===' '||e.key==='Enter')action();
  if(e.key==='p'||e.key==='Escape'){if(state==='play')state='pause';else if(state==='pause')state='play'}
});
addEventListener('keyup',e=>keys[e.key.toLowerCase()]=false);
function mpos(e){const r=cv.getBoundingClientRect();mouseX=(e.clientX-r.left)*W/r.width;usingMouse=true}
cv.addEventListener('mousemove',mpos);
cv.addEventListener('mousedown',e=>{mpos(e);action()});
cv.addEventListener('touchstart',e=>{mpos(e.touches[0]);action();e.preventDefault()},{passive:false});
cv.addEventListener('touchmove',e=>{mpos(e.touches[0]);e.preventDefault()},{passive:false});
addEventListener('blur',()=>{if(state==='play')state='pause'});

function dropPower(x,y){
  if(Math.random()>.16)return;
  const types=['W','S','M','L','T'];// wide, sticky, multi, life, slow
  powers.push({x,y,t:types[Math.floor(Math.random()*types.length)]});
}
function applyPower(t){
  beep(700,.25,'triangle',.07,500);flash=.25;
  if(t==='W'){paddle.tw=160;pop(paddle.x,H-50,'WIDE!',180)}
  if(t==='S'){sticky=1;pop(paddle.x,H-50,'STICKY!',120)}
  if(t==='L'){lives=Math.min(6,lives+1);pop(paddle.x,H-50,'+1 LIFE',0)}
  if(t==='T'){slow=600;pop(paddle.x,H-50,'SLOW',200)}
  if(t==='M'){
    const src=balls.filter(b=>!b.stuck)[0];
    if(src){for(const d of[-.5,.5]){const a=Math.atan2(src.vy,src.vx)+d,s=Math.hypot(src.vx,src.vy);
      balls.push({x:src.x,y:src.y,vx:Math.cos(a)*s,vy:Math.sin(a)*s,stuck:false})}}
    pop(paddle.x,H-50,'MULTI!',300);
  }
}
const pcol={W:200,S:120,M:300,L:0,T:190};

function hitBrick(b,br){
  if(br.u){beep(180,.07,'square',.05);br.hit=6;shake=Math.max(shake,2);return}
  br.hp--;br.hit=6;combo++;
  const pts=10*(1+Math.min(combo,10)*.2)|0;
  if(br.hp<=0){
    score+=pts*br.max;
    burst(br.x+BW/2,br.y+BH/2,br.hue,18,5);
    pop(br.x+BW/2,br.y+BH/2,'+'+pts*br.max,br.hue);
    beep(300+Math.min(combo,12)*50,.12,'square',.06,200);
    shake=Math.max(shake,4);
    dropPower(br.x+BW/2,br.y+BH/2);
    bricks.splice(bricks.indexOf(br),1);
  }else{score+=pts;burst(br.x+BW/2,br.y+BH/2,br.hue,6,3);beep(260,.07,'square',.05)}
  if(score>best){best=score;localStorage.setItem('bo_best',best)}
}

function update(){
  stateT++;
  // paddle
  if(state==='play'){
    const sp=10;
    if(keys['arrowleft']||keys['a']){paddle.x-=sp;}
    if(keys['arrowright']||keys['d']){paddle.x+=sp;}
    if(usingMouse&&mouseX!==null)paddle.x+=(mouseX-paddle.x)*.5;
    paddle.w+=(paddle.tw-paddle.w)*.15;
    paddle.x=Math.max(paddle.w/2,Math.min(W-paddle.w/2,paddle.x));
    if(slow>0)slow--;
    const py=H-40;
    for(const b of balls){
      if(b.stuck){b.x=paddle.x;b.y=py-PH/2-BR;continue}
      const k=slow>0?.65:1;
      // sub-steps to avoid tunneling
      const steps=3;
      for(let s=0;s<steps;s++){
        b.x+=b.vx*k/steps;b.y+=b.vy*k/steps;
        if(b.x<BR){b.x=BR;b.vx=Math.abs(b.vx);beep(200,.04,'sine',.05)}
        if(b.x>W-BR){b.x=W-BR;b.vx=-Math.abs(b.vx);beep(200,.04,'sine',.05)}
        if(b.y<BR){b.y=BR;b.vy=Math.abs(b.vy);beep(200,.04,'sine',.05)}
        // paddle
        if(b.vy>0&&b.y+BR>=py-PH/2&&b.y-BR<=py+PH/2&&b.x>=paddle.x-paddle.w/2-BR&&b.x<=paddle.x+paddle.w/2+BR){
          const rel=(b.x-paddle.x)/(paddle.w/2),a=-Math.PI/2+rel*1.1,sp2=speed();
          b.vx=Math.cos(a)*sp2;b.vy=Math.sin(a)*sp2;b.y=py-PH/2-BR;
          combo=0;shake=3;burst(b.x,b.y+BR,200,6,2);beep(330,.06,'triangle',.08);
          if(sticky){b.stuck=true;b.vx=b.vy=0;sticky=0}
        }
        // bricks
        for(const br of bricks){
          if(b.x+BR>br.x&&b.x-BR<br.x+BW&&b.y+BR>br.y&&b.y-BR<br.y+BH){
            const ox=Math.min(b.x+BR-br.x,br.x+BW-(b.x-BR)),oy=Math.min(b.y+BR-br.y,br.y+BH-(b.y-BR));
            if(ox<oy){b.vx=(b.x<br.x+BW/2?-1:1)*Math.abs(b.vx);b.x+=b.vx>0?ox:-ox}
            else{b.vy=(b.y<br.y+BH/2?-1:1)*Math.abs(b.vy);b.y+=b.vy>0?oy:-oy}
            hitBrick(b,br);break;
          }
        }
      }
      trail.push({x:b.x,y:b.y,l:1});
    }
    balls=balls.filter(b=>b.y<H+20);
    if(!balls.length){
      lives--;shake=14;flash=.4;beep(120,.5,'sawtooth',.08,-80);
      burst(paddle.x,H-40,0,30,6);
      if(lives<=0){state='over';stateT=0}else resetBall();
    }
    // powerups
    for(const p of powers){p.y+=2.2;
      if(p.y>H-40-PH&&p.y<H-30&&Math.abs(p.x-paddle.x)<paddle.w/2+10){p.dead=1;applyPower(p.t)}
      else if(p.y>H+10)p.dead=1}
    powers=powers.filter(p=>!p.dead);
    // clear
    if(!bricks.some(b=>!b.u)){
      score+=500;beep(600,.5,'triangle',.08,600);flash=.5;
      for(let i=0;i<6;i++)burst(Math.random()*W,Math.random()*300+50,hues[i],25,6);
      state='clear';stateT=0;
    }
  }
  if(state==='clear'&&stateT>110){
    if(level+1>=LEVELS.length*2){state='win'}
    else{startLevel(level+1);state='play'}
  }
  // fx
  for(const p of parts){p.x+=p.vx;p.y+=p.vy;p.vy+=.12;p.vx*=.98;p.life-=.025}
  parts=parts.filter(p=>p.life>0);
  for(const p of pops){p.y-=.8;p.life-=.02}
  pops=pops.filter(p=>p.life>0);
  for(const t of trail)t.l-=.12;
  trail=trail.filter(t=>t.l>0);
  for(const b of bricks)if(b.hit>0)b.hit--;
  for(const s of stars){s.y+=s.z*.4;if(s.y>H){s.y=0;s.x=Math.random()*W}}
  shake*=.85;flash*=.9;if(bannerT>0)bannerT--;
}

function txt(s,x,y,size,col='#fff',align='center',glow=null){
  ctx.font=`bold ${size}px ui-monospace,Menlo,Consolas,monospace`;
  ctx.textAlign=align;
  if(glow){ctx.shadowColor=glow;ctx.shadowBlur=14}
  ctx.fillStyle=col;ctx.fillText(s,x,y);ctx.shadowBlur=0;
}

function draw(){
  ctx.save();
  ctx.clearRect(0,0,W,H);
  const g=ctx.createLinearGradient(0,0,0,H);g.addColorStop(0,'#10102a');g.addColorStop(1,'#07070f');
  ctx.fillStyle=g;ctx.fillRect(0,0,W,H);
  for(const s of stars){ctx.fillStyle=`rgba(180,220,255,${s.z*.6})`;ctx.fillRect(s.x,s.y,s.z*2,s.z*2)}
  if(shake>.3)ctx.translate((Math.random()-.5)*shake,(Math.random()-.5)*shake);

  // bricks
  for(const b of bricks){
    const l=b.u?55:40+ (b.hp/b.max)*20+b.hit*4;
    ctx.fillStyle=b.u?`hsl(220,10%,${l}%)`:`hsl(${b.hue},85%,${l}%)`;
    ctx.shadowColor=b.u?'#889':`hsl(${b.hue},90%,55%)`;ctx.shadowBlur=b.hit?18:6;
    ctx.beginPath();ctx.roundRect(b.x,b.y,BW,BH,4);ctx.fill();ctx.shadowBlur=0;
    ctx.fillStyle='rgba(255,255,255,.22)';ctx.fillRect(b.x+3,b.y+2,BW-6,4);
    if(!b.u&&b.max>1){ctx.fillStyle='rgba(0,0,0,.35)';for(let i=0;i<b.hp;i++)ctx.fillRect(b.x+8+i*9,b.y+BH-8,6,4)}
  }
  // powerups
  for(const p of powers){
    ctx.fillStyle=`hsl(${pcol[p.t]},90%,55%)`;ctx.shadowColor=ctx.fillStyle;ctx.shadowBlur=12;
    ctx.beginPath();ctx.roundRect(p.x-12,p.y-10,24,20,6);ctx.fill();ctx.shadowBlur=0;
    txt(p.t,p.x,p.y+5,14,'#000');
  }
  // paddle
  const py=H-40;
  ctx.fillStyle='#4df';ctx.shadowColor='#0ff';ctx.shadowBlur=16;
  ctx.beginPath();ctx.roundRect(paddle.x-paddle.w/2,py-PH/2,paddle.w,PH,7);ctx.fill();ctx.shadowBlur=0;
  if(sticky){ctx.fillStyle='#6f6';ctx.fillRect(paddle.x-paddle.w/2+6,py-PH/2-3,paddle.w-12,3)}
  // trail & balls
  for(const t of trail){ctx.fillStyle=`rgba(255,255,255,${t.l*.3})`;ctx.beginPath();ctx.arc(t.x,t.y,BR*t.l,0,6.283);ctx.fill()}
  for(const b of balls){
    ctx.fillStyle='#fff';ctx.shadowColor=slow>0?'#6cf':'#fff';ctx.shadowBlur=18;
    ctx.beginPath();ctx.arc(b.x,b.y,BR,0,6.283);ctx.fill();ctx.shadowBlur=0;
  }
  // particles
  for(const p of parts){ctx.globalAlpha=Math.max(0,p.life);ctx.fillStyle=`hsl(${p.hue},90%,60%)`;ctx.fillRect(p.x,p.y,p.sz,p.sz)}
  ctx.globalAlpha=1;
  for(const p of pops){ctx.globalAlpha=Math.max(0,p.life);txt(p.t,p.x,p.y,16,`hsl(${p.hue},90%,70%)`);}
  ctx.globalAlpha=1;
  ctx.restore();

  if(flash>.02){ctx.fillStyle=`rgba(255,255,255,${flash*.35})`;ctx.fillRect(0,0,W,H)}

  // HUD
  txt('SCORE '+score,16,30,20,'#fff','left','#0ff');
  txt('LEVEL '+(level+1),W/2,30,20,'#ff8','center','#fa0');
  txt('♥'.repeat(lives),W-16,30,20,'#f46','right','#f04');
  txt('BEST '+best,16,52,12,'#789','left');
  if(combo>2&&state==='play')txt('COMBO x'+combo,W-16,52,14,'#fc4','right');
  if(slow>0)txt('SLOW',W/2,52,12,'#6cf');

  if(bannerT>0&&state==='play'){
    ctx.globalAlpha=Math.min(1,bannerT/40);
    txt('LEVEL '+(level+1),W/2,H/2+40,48,'#fff','center','#0ff');ctx.globalAlpha=1;
  }
  if(state==='play'&&balls.some(b=>b.stuck))txt('SPACE / CLICK to launch',W/2,H-90,16,'#9ab');

  const overlay=(a,b,c)=>{
    ctx.fillStyle='rgba(5,5,15,.75)';ctx.fillRect(0,0,W,H);
    txt(a,W/2,H/2-30,56,'#fff','center','#0ff');
    if(b)txt(b,W/2,H/2+15,22,'#fc4');
    if(c)txt(c,W/2,H/2+55,16,'#9ab');
  };
  if(state==='title'){
    overlay('BREAKOUT','Clear all the bricks. Don\'t drop the ball.','Move: mouse or ←/→ (A/D) · Launch: click or SPACE · Pause: P');
    txt('Press SPACE or click to start',W/2,H/2+100,18,'#fff','center','#0ff');
    txt('Power-ups: W wide · S sticky · M multiball · T slow · L life',W/2,H/2+135,13,'#789');
  }
  if(state==='pause')overlay('PAUSED','','Press P or click to resume');
  if(state==='over')overlay('GAME OVER','Score '+score+(score>=best?'  — NEW BEST!':''),'Press SPACE or click to play again');
  if(state==='win')overlay('YOU WIN!','Final score '+score,'Press SPACE or click to play again');
  if(state==='clear'){
    txt('LEVEL CLEAR!  +500',W/2,H/2,44,'#fff','center','#f0f');
  }
}

let last=0,acc=0;
function frame(t){
  acc+=Math.min(50,t-last);last=t;
  while(acc>=1000/60){if(state!=='pause')update();acc-=1000/60}
  draw();requestAnimationFrame(frame);
}
paddle.x=W/2;buildLevel(0);resetBall();
requestAnimationFrame(t=>{last=t;frame(t)});
})();
</script>
</body>
</html>

Compare with

Claude Sonnet 5.5: other attempts