Models 44

Muse Ember

Open in new window

Running live in a sandboxed frame. Click inside it before using the keyboard.

How it went

Total time
1 min 2 s
Cost
$0.017
Output tokens
33,886
Spent thinking
23,363 tokens
Speed
559.9 tok/s
Console errors
0
First token after
1.9 s
First visible text after
50.7 s
Prompt tokens
375
Code size
29.0 KB
Finish reason
stop
Served by
Meta
Model id
meta/muse-ember
Reasoning sent
{"effort":"max"}
Max output
943,718 tokens
Generated
Nov 12, 2026

What it was asked

The prompt
“i want a breakout game where the paddle is a hamburger and every brick you break explodes into tons of little hearts”
System prompt, sent with every prompt
You are generating a self-contained web demo. It will be rendered automatically in a sandboxed iframe and compared side by side with the output of other AI models given the exact same task.

Output rules:
- Reply with exactly ONE fenced code block containing the complete file: ```html (or ```svg when the task asks for an SVG). No text before or after the code block.
- Everything must be inline: CSS in <style>, JavaScript in <script>. No external files, images, fonts or network requests, except the CDN URLs explicitly allowed by the task.
- Do not use localStorage, sessionStorage, cookies, IndexedDB, alert(), confirm(), prompt() or window.open(): they are blocked in the sandbox and will throw.
- The page must look right in a 1280×800 viewport and adapt gracefully down to 375px wide. No horizontal scrollbar.
- Something meaningful must be visible on first paint: a screenshot is taken automatically about 3 seconds after load, without any interaction.
- Everything that makes the demo interesting must be visible within the first seconds: nothing hidden behind a high score, a later level or a long play session.
- Games must start in a self-playing demo mode (a simple AI plays) behind a "Click or press a key to start" message, so the game can be judged in action without playing.
- The iframe only receives keyboard events after the user clicks it: if the demo uses the keyboard, display a clear "Click or press a key to start" message.
- The code must run with zero errors in the console of the latest Chrome.

Code run-1.html · 732 lines

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Heart Breaker — Hamburger Breakout</title>
<style>
  *{box-sizing:border-box}
  html,body{margin:0;padding:0;overflow-x:hidden}
  body{
    font-family:"Trebuchet MS","Segoe UI",system-ui,-apple-system,sans-serif;
    background:#ffe5ec;
    background-image:radial-gradient(rgba(255,65,108,.14) 1.6px, transparent 1.7px);
    background-size:24px 24px;
    color:#590d22;
    min-height:100vh;
  }
  .app{max-width:1060px;margin:0 auto;padding:14px 14px 20px}
  header{
    display:flex;align-items:center;justify-content:space-between;gap:14px;flex-wrap:wrap;
    background:rgba(255,255,255,.82);border:2px solid #ffb3c6;border-radius:20px;
    padding:10px 16px;box-shadow:0 8px 24px rgba(201,24,74,.14);backdrop-filter:blur(4px);
  }
  .logo{display:flex;align-items:center;gap:10px;line-height:1}
  .logo .burger{font-size:38px;display:inline-block;animation:wiggle 2.2s ease-in-out infinite;transform-origin:center}
  @keyframes wiggle{0%,100%{transform:rotate(-5deg)}50%{transform:rotate(6deg) translateY(-2px)}}
  .logo h1{font-size:25px;margin:0;letter-spacing:.5px;color:#590d22}
  .logo h1 span{color:#ff416c}
  .logo small{display:block;font-size:10px;letter-spacing:3px;color:#ff6b9d;font-weight:800;margin-top:3px}
  .stats{display:flex;gap:9px;flex-wrap:wrap}
  .stat{background:#fff;border:2px solid #ffe5ec;border-radius:14px;padding:5px 12px;min-width:82px;text-align:center;box-shadow:0 3px 10px rgba(255,65,108,.10)}
  .stat label{display:block;font-size:9px;letter-spacing:2px;font-weight:900;color:#ff416c}
  .stat strong{display:inline-block;font-size:20px;color:#590d22;line-height:1.15;transition:transform .15s}
  .stat.hot strong{color:#ff416c;transform:scale(1.18)}
  .actions{display:flex;gap:8px}
  button{font-family:inherit;cursor:pointer;border:2px solid #ffb3c6;background:#fff;color:#590d22;border-radius:999px;padding:8px 14px;font-weight:800;font-size:13px;box-shadow:0 3px 0 #ffb3c6;transition:transform .1s, box-shadow .1s}
  button:hover{transform:translateY(-1px)}
  button:active{transform:translateY(2px);box-shadow:0 1px 0 #ffb3c6}
  .frame{
    position:relative;margin:14px auto 0;max-width:840px;
    border:4px solid #ff8fab;border-radius:24px;overflow:hidden;background:#fff0f3;
    box-shadow:0 18px 40px rgba(201,24,74,.22), 0 4px 0 rgba(255,143,171,.6);
  }
  canvas{display:block;width:100%;height:auto;touch-action:none;background:#fff5f7}
  .overlay{
    position:absolute;inset:0;z-index:5;display:flex;align-items:center;justify-content:center;
    padding:16px;background:rgba(255,240,243,.42);backdrop-filter:blur(1.2px);
  }
  .hidden{display:none!important}
  .card{
    background:#fff;border:3px solid #ffb3c6;border-radius:24px;padding:20px 24px;text-align:center;
    max-width:440px;width:100%;box-shadow:0 16px 36px rgba(201,24,74,.22);
  }
  .card .big{font-size:46px;line-height:1;animation:wiggle 2s ease-in-out infinite;display:inline-block}
  .card h2{margin:8px 0 6px;font-size:30px;letter-spacing:.6px;color:#590d22}
  .card h2 span{color:#ff416c}
  .card p{margin:6px 0;color:#800f2f;line-height:1.45;font-size:15px}
  .cta{
    display:inline-block;margin:14px auto 8px;padding:12px 20px;border-radius:999px;color:#fff;font-weight:900;font-size:16px;
    background:linear-gradient(135deg,#ff416c,#ff6b9d);box-shadow:0 8px 20px rgba(255,65,108,.4);
    animation:pulse 1.35s ease-in-out infinite;
  }
  @keyframes pulse{0%,100%{transform:scale(1)}50%{transform:scale(1.06)}}
  .demo-note{font-size:13px;color:#ff416c;font-weight:700}
  .hint{display:inline-block;margin-top:10px;background:#fff0f3;border-radius:999px;padding:7px 12px;font-size:12px;color:#590d22;font-weight:700}
  .toast{
    position:absolute;left:50%;bottom:14px;transform:translate(-50%,10px);z-index:6;pointer-events:none;
    background:#590d22;color:#fff;padding:9px 16px;border-radius:999px;font-weight:800;font-size:14px;
    opacity:0;transition:opacity .25s,transform .25s;white-space:nowrap;max-width:92%;overflow:hidden;text-overflow:ellipsis;
    box-shadow:0 8px 20px rgba(0,0,0,.18);
  }
  .toast.show{opacity:1;transform:translate(-50%,0)}
  .pause-tag{
    position:absolute;left:50%;top:12px;transform:translateX(-50%);z-index:6;background:#fff;border:2px solid #ffb3c6;
    color:#590d22;font-weight:900;padding:7px 14px;border-radius:999px;font-size:13px;box-shadow:0 6px 16px rgba(0,0,0,.12);white-space:nowrap;
  }
  .how{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;max-width:840px;margin:12px auto 0}
  .how-item{background:rgba(255,255,255,.85);border:2px solid #ffe5ec;border-radius:16px;padding:10px 12px;display:flex;gap:10px;align-items:center}
  .how-item>span{font-size:26px}
  .how-item b{font-size:13px;display:block}
  .how-item p{margin:2px 0 0;font-size:12px;color:#800f2f;line-height:1.35}
  .footer{text-align:center;font-size:12px;color:#ff6b9d;font-weight:700;margin-top:12px}
  @media (max-width:640px){
    .app{padding:10px 8px 14px}
    header{padding:8px 10px;border-radius:16px}
    .logo h1{font-size:19px}
    .logo .burger{font-size:30px}
    .logo small{letter-spacing:2px;font-size:8px}
    .stat{min-width:64px;padding:4px 8px;border-radius:11px}
    .stat strong{font-size:16px}
    button{padding:7px 10px;font-size:12px}
    .frame{border-width:3px;border-radius:18px;margin-top:10px}
    .card{padding:16px 14px}
    .card h2{font-size:24px}
    .card .big{font-size:36px}
    .cta{font-size:14px;padding:10px 16px}
    .how{grid-template-columns:1fr;gap:8px}
    .toast{font-size:12px}
  }
</style>
</head>
<body>
<div class="app">
  <header>
    <div class="logo">
      <span class="burger">🍔</span>
      <div>
        <h1>Heart <span>Breaker</span></h1>
        <small>HAMBURGER BREAKOUT</small>
      </div>
    </div>
    <div class="stats">
      <div class="stat"><label>SCORE</label><strong id="score">0</strong></div>
      <div class="stat"><label>LIVES</label><strong id="lives">♥♥♥</strong></div>
      <div class="stat"><label>LEVEL</label><strong id="level">1</strong></div>
      <div class="stat" id="comboStat"><label>COMBO</label><strong id="combo">x1</strong></div>
    </div>
    <div class="actions">
      <button type="button" id="pauseBtn">⏸ Pause</button>
      <button type="button" id="resetBtn">↺ Restart</button>
    </div>
  </header>

  <div class="frame" id="frame">
    <canvas id="game" width="900" height="620"></canvas>

    <div class="overlay" id="overlay">
      <div class="card">
        <span class="big">🍔</span>
        <h2>HEART <span>BREAKER</span></h2>
        <p>Your paddle is a <b>hamburger</b>.<br>Every brick you break <b>explodes into tons of little hearts!</b> 💥❤️</p>
        <div class="cta">👆 Click or press a key to start</div>
        <p class="demo-note">🤖 Demo mode — the hamburger AI is playing for you…</p>
        <div class="hint">🖱️ Mouse / Touch &nbsp;·&nbsp; ← → Arrow keys &nbsp;·&nbsp; Space = Pause</div>
      </div>
    </div>

    <div class="overlay hidden" id="overlayEnd">
      <div class="card">
        <span class="big">💔</span>
        <h2>OUT OF <span>LIVES!</span></h2>
        <p>The burger needs a rest…</p>
        <p><b>Final score: <span id="finalScore">0</span></b> &nbsp;·&nbsp; Level <span id="finalLevel">1</span></p>
        <button type="button" id="playAgain" style="font-size:16px;padding:12px 22px;background:linear-gradient(135deg,#ff416c,#ff6b9d);color:#fff;border-color:#ff8fab">🍔 Play Again</button>
        <div class="hint">or press Enter</div>
      </div>
    </div>

    <div class="pause-tag hidden" id="pauseTag">⏸ Paused — press Space to resume</div>
    <div class="toast" id="toast"></div>
  </div>

  <div class="how">
    <div class="how-item"><span>🍔</span><div><b>Steer the burger</b><p>Mouse, touch, or ← → arrow keys. Angle your shots!</p></div></div>
    <div class="how-item"><span>💥</span><div><b>Smash the bricks</b><p>Each brick bursts into a shower of 30+ spinning hearts.</p></div></div>
    <div class="how-item"><span>❤️</span><div><b>Don't drop the ball</b><p>The heart-ball is fast! You have 3 lives per game.</p></div></div>
  </div>
  <div class="footer">Made with ❤️ — every brick = tons of hearts</div>
</div>

<script>
(function(){
'use strict';
var canvas=document.getElementById('game');
var ctx=canvas.getContext('2d');
var W=900,H=620,SCALE=2;
canvas.width=W*SCALE; canvas.height=H*SCALE;
ctx.setTransform(SCALE,0,0,SCALE,0,0);

var scoreEl=document.getElementById('score'),
    livesEl=document.getElementById('lives'),
    levelEl=document.getElementById('level'),
    comboEl=document.getElementById('combo'),
    comboStat=document.getElementById('comboStat'),
    overlay=document.getElementById('overlay'),
    overlayEnd=document.getElementById('overlayEnd'),
    finalScoreEl=document.getElementById('finalScore'),
    finalLevelEl=document.getElementById('finalLevel'),
    toastEl=document.getElementById('toast'),
    pauseTag=document.getElementById('pauseTag'),
    pauseBtn=document.getElementById('pauseBtn'),
    resetBtn=document.getElementById('resetBtn'),
    playAgainBtn=document.getElementById('playAgain'),
    frame=document.getElementById('frame');

function clamp(v,a,b){return Math.max(a,Math.min(b,v));}
function rand(a,b){return a+Math.random()*(b-a);}
function pick(arr){return arr[Math.floor(Math.random()*arr.length)];}

var heartColors=['#ff416c','#ff6b9d','#ff8fab','#ff2e63','#ffb3c6','#ff5d8f','#ff87a5'];
var rowColors=[
 {main:'#ff416c',light:'#ff8fab',dark:'#c9184a',points:60},
 {main:'#ff8500',light:'#ffb703',dark:'#e36414',points:50},
 {main:'#ffb703',light:'#ffd60a',dark:'#f48c06',points:40},
 {main:'#2ec4b6',light:'#6ee7d8',dark:'#0a9396',points:30},
 {main:'#4361ee',light:'#4cc9f0',dark:'#3a0ca3',points:20},
 {main:'#9b5de5',light:'#c77dff',dark:'#5a189a',points:10}
];

var score=0,lives=3,level=1,combo=0,comboTimer=0;
var mode='demo'; // demo = AI plays
var paused=false,gameOver=false;
var paddle={x:W/2,w:132,h:40,y:H-48,tilt:0};
var ball={x:W/2,y:H-90,vx:240,vy:-340,r:11,speed:430,stuck:false,stuckTimer:0};
var bricks=[],hearts=[],floaters=[],bgHearts=[];
var paddleSquash=0,shake=0,time=0,trailTimer=0,bgTimer=0,demoRestartTimer=0;
var keys={left:false,right:false};
var mouseTarget=null;
var actx=null;
var toastTimer=null;

var dots=[];
for(var di=0;di<42;di++) dots.push({x:rand(16,W-16),y:rand(16,H-16),r:rand(2,6)});

function rr(x,y,w,h,r){
  r=Math.min(r,w/2,h/2);
  ctx.beginPath();
  ctx.moveTo(x+r,y);
  ctx.arcTo(x+w,y,x+w,y+h,r);
  ctx.arcTo(x+w,y+h,x,y+h,r);
  ctx.arcTo(x,y+h,x,y,r);
  ctx.arcTo(x,y,x+w,y,r);
  ctx.closePath();
}
function heartPath(s){
  ctx.beginPath();
  ctx.moveTo(0,s*0.28);
  ctx.bezierCurveTo(s*0.55,-s*0.35,s*0.95,s*0.10,0,s*0.85);
  ctx.bezierCurveTo(-s*0.95,s*0.10,-s*0.55,-s*0.35,0,s*0.28);
  ctx.closePath();
}
function drawHeart(x,y,size,rot,color,alpha){
  ctx.save();
  ctx.translate(x,y); ctx.rotate(rot); ctx.globalAlpha=clamp(alpha,0,1);
  heartPath(size);
  ctx.fillStyle=color; ctx.fill();
  ctx.strokeStyle='rgba(255,255,255,0.85)'; ctx.lineWidth=1.1; ctx.stroke();
  ctx.restore();
}

function buildLevel(lv){
  bricks=[];
  var rows=6,cols=10,top=66,bh=28,gap=6,margin=20;
  var avail=W-margin*2-gap*(cols-1);
  var bw=avail/cols;
  for(var r=0;r<rows;r++){
    for(var c=0;c<cols;c++){
      var hp=(lv>=2 && r<=1 && Math.random()<0.28)?2:1;
      bricks.push({x:margin+c*(bw+gap),y:top+r*(bh+gap),w:bw,h:bh,hp:hp,maxHp:hp,row:r,color:rowColors[r],alive:true});
    }
  }
}
function resetBall(stuckMs){
  ball.x=paddle.x; ball.y=paddle.y-36;
  ball.speed=Math.min(620,420+(level-1)*35);
  var ang=rand(-0.35,0.35);
  ball.vx=Math.sin(ang)*ball.speed;
  ball.vy=-Math.cos(ang)*ball.speed;
  ball.stuck=stuckMs>0;
  ball.stuckTimer=stuckMs/1000;
}
function updateHUD(){
  scoreEl.textContent=score;
  livesEl.textContent='♥'.repeat(Math.max(0,lives));
  levelEl.textContent=level;
  var c=Math.max(1,combo);
  comboEl.textContent='x'+c;
  if(combo>=3) comboStat.classList.add('hot'); else comboStat.classList.remove('hot');
}
function spawnHearts(x,y,count,power){
  power=power||1;
  for(var i=0;i<count;i++){
    if(hearts.length>650) hearts.shift();
    var ang=Math.random()*Math.PI*2;
    var spd=rand(60,430)*power;
    var life=rand(0.9,1.9);
    hearts.push({
      x:x+rand(-7,7), y:y+rand(-5,5),
      vx:Math.cos(ang)*spd, vy:Math.sin(ang)*spd-150*power,
      size:rand(6,16)*(power>1.1?1.25:1),
      rot:rand(0,Math.PI*2), vr:rand(-6,6),
      life:life, maxLife:life, color:pick(heartColors), seed:rand(0,10)
    });
  }
}
function spawnFloater(x,y,text,color){
  floaters.push({x:x,y:y,text:text,color:color||'#ff416c',life:1.15,max:1.15});
}
function showToast(msg){
  toastEl.textContent=msg;
  toastEl.classList.add('show');
  if(toastTimer) clearTimeout(toastTimer);
  toastTimer=setTimeout(function(){toastEl.classList.remove('show');},2200);
}
function initAudio(){
  if(!actx){ try{ actx=new (window.AudioContext||window.webkitAudioContext)(); }catch(e){ actx=null; } }
  if(actx && actx.state==='suspended'){ actx.resume(); }
}
function tone(freq,dur,type,vol,slideTo){
  if(!actx) return;
  dur=dur||0.08; type=type||'triangle'; vol=vol||0.1;
  try{
    var o=actx.createOscillator(),g=actx.createGain();
    o.type=type; o.frequency.setValueAtTime(freq,actx.currentTime);
    if(slideTo) o.frequency.exponentialRampToValueAtTime(slideTo,actx.currentTime+dur);
    g.gain.setValueAtTime(vol,actx.currentTime);
    g.gain.exponentialRampToValueAtTime(0.001,actx.currentTime+dur);
    o.connect(g); g.connect(actx.destination);
    o.start(); o.stop(actx.currentTime+dur);
  }catch(e){}
}

function hitBrick(b){
  var cx=b.x+b.w/2, cy=b.y+b.h/2;
  if(b.hp>1){
    b.hp--; spawnHearts(cx,cy,16,0.7); shake=4;
    tone(300,0.08,'square',0.10);
    spawnFloater(cx,cy,'CRACK!','#590d22');
    return;
  }
  b.alive=false;
  spawnHearts(cx,cy,36,1);
  for(var i=0;i<5;i++) spawnHearts(cx+rand(-22,22),cy+rand(-8,8),1,1.3);
  shake=5;
  tone(rand(520,840),0.09,'triangle',0.14);
  if(comboTimer>0) combo++; else combo=1;
  comboTimer=1.6;
  var pts=b.color.points+(combo-1)*5;
  score+=pts;
  spawnFloater(cx,cy,'+'+pts+(combo>1?'  x'+combo:''),'#ff416c');
  ball.speed=Math.min(650,ball.speed+4);
  var mag=Math.hypot(ball.vx,ball.vy)||1;
  ball.vx=ball.vx/mag*ball.speed; ball.vy=ball.vy/mag*ball.speed;
  updateHUD();
  var allDead=true;
  for(var j=0;j<bricks.length;j++) if(bricks[j].alive){allDead=false;break;}
  if(allDead) levelClear();
}
function levelClear(){
  level++;
  if(lives<5) lives++;
  tone(523,0.14,'triangle',0.14); tone(659,0.14,'triangle',0.12); tone(784,0.2,'triangle',0.12);
  spawnFloater(W/2,H/2-30,'LEVEL '+level+'! ❤️','#ff416c');
  for(var i=0;i<70;i++) spawnHearts(rand(40,W-40),rand(50,H/2),1,1.2);
  showToast('Level '+level+'! Ball is faster ❤️ +1 life');
  updateHUD();
  buildLevel(level);
  resetBall(700);
}
function loseLife(){
  tone(420,0.28,'sawtooth',0.08,110);
  spawnHearts(ball.x,H-30,22,0.8);
  lives--; updateHUD();
  if(lives<=0){
    gameOver=true;
    if(mode==='demo'){ demoRestartTimer=1.5; showToast('Demo restarting… 🍔'); }
    else { showGameOver(); }
  }else{
    showToast(lives+(lives===1?' life':' lives')+' left — go! 💔');
    resetBall(900);
  }
}
function showGameOver(){
  finalScoreEl.textContent=score;
  finalLevelEl.textContent=level;
  overlayEnd.classList.remove('hidden');
  paused=false; pauseTag.classList.add('hidden'); pauseBtn.textContent='⏸ Pause';
}
function resetGame(){
  score=0; lives=3; level=1; combo=0; comboTimer=0;
  hearts=[]; floaters=[]; gameOver=false; paused=false;
  paddle.x=W/2; paddle.tilt=0;
  buildLevel(1); resetBall(0);
  pauseTag.classList.add('hidden'); pauseBtn.textContent='⏸ Pause';
  updateHUD();
}
function togglePause(force){
  if(gameOver) return;
  paused=(typeof force==='boolean')?force:!paused;
  pauseTag.classList.toggle('hidden',!paused);
  pauseBtn.textContent=paused?'▶ Resume':'⏸ Pause';
  if(!paused) initAudio();
}
function startGame(){
  if(mode==='demo'){
    mode='playing';
    overlay.classList.add('hidden');
    initAudio();
    tone(440,0.09,'triangle',0.12); tone(660,0.1,'triangle',0.12);
    showToast('Your turn! 🍔 Move with mouse or ← →');
  }else if(paused){
    togglePause(false);
  }
}

function wallPuff(x,y){
  spawnHearts(x,y,3,0.4);
  tone(180,0.05,'square',0.06);
}
function stepBall(dt){
  var prevX=ball.x, prevY=ball.y;
  ball.x+=ball.vx*dt; ball.y+=ball.vy*dt;
  if(ball.x<ball.r+8){ ball.x=ball.r+8; ball.vx=Math.abs(ball.vx); wallPuff(ball.x,ball.y); }
  if(ball.x>W-ball.r-8){ ball.x=W-ball.r-8; ball.vx=-Math.abs(ball.vx); wallPuff(ball.x,ball.y); }
  if(ball.y<ball.r+8){ ball.y=ball.r+8; ball.vy=Math.abs(ball.vy); wallPuff(ball.x,ball.y); }
  if(ball.y-ball.r>H+24){ loseLife(); return; }
  // paddle (hamburger)
  if(ball.vy>0){
    var surface=paddle.y-14;
    if(ball.y+ball.r>=surface && ball.y-ball.r<=paddle.y+16 && Math.abs(ball.x-paddle.x)<=paddle.w/2+ball.r){
      var rel=clamp((ball.x-paddle.x)/(paddle.w/2),-1,1);
      var ang=rel*Math.PI/3;
      ball.speed=Math.min(650,ball.speed+5);
      ball.vx=Math.sin(ang)*ball.speed;
      ball.vy=-Math.cos(ang)*ball.speed;
      ball.y=surface-ball.r-1;
      paddleSquash=1;
      spawnHearts(ball.x,surface-4,7,0.5);
      tone(240+Math.abs(rel)*130,0.07,'triangle',0.12);
    }
  }
  // bricks
  for(var i=0;i<bricks.length;i++){
    var b=bricks[i]; if(!b.alive) continue;
    var cx=clamp(ball.x,b.x,b.x+b.w);
    var cy=clamp(ball.y,b.y,b.y+b.h);
    var dx=ball.x-cx, dy=ball.y-cy;
    if(dx*dx+dy*dy<=ball.r*ball.r){
      if(prevY+ball.r<=b.y+3){ ball.vy=-Math.abs(ball.vy); ball.y=b.y-ball.r-1; }
      else if(prevY-ball.r>=b.y+b.h-3){ ball.vy=Math.abs(ball.vy); ball.y=b.y+b.h+ball.r+1; }
      else if(prevX+ball.r<=b.x+3){ ball.vx=-Math.abs(ball.vx); ball.x=b.x-ball.r-1; }
      else if(prevX-ball.r>=b.x+b.w-3){ ball.vx=Math.abs(ball.vx); ball.x=b.x+b.w+ball.r+1; }
      else { ball.vy=-ball.vy; }
      hitBrick(b);
      break;
    }
  }
}
function aiMove(dt){
  var target=ball.x;
  if(ball.vy>0){
    var t=(paddle.y-14-ball.y)/ball.vy;
    if(t>0){
      var x=ball.x+ball.vx*t;
      var min=18,max=W-18,range=max-min,period=range*2;
      var y=(x-min)%period; if(y<0) y+=period; if(y>range) y=period-y;
      target=min+y;
    }
  }else{
    target=ball.x+ball.vx*0.25;
  }
  var dx=target-paddle.x;
  var maxStep=630*dt;
  paddle.x+=clamp(dx,-maxStep,maxStep);
}
function updateParticles(dt){
  var i,h;
  for(i=hearts.length-1;i>=0;i--){
    h=hearts[i]; h.life-=dt;
    if(h.life<=0){ hearts.splice(i,1); continue; }
    h.vy+=620*dt; h.vx*=(1-0.9*dt); h.vy*=(1-0.15*dt);
    h.x+=h.vx*dt+Math.sin(time*6+h.seed)*18*dt;
    h.y+=h.vy*dt; h.rot+=h.vr*dt;
    if(h.y>H+18){ h.y=H+18; h.vy*=-0.35; h.vx*=0.7; }
  }
  for(i=floaters.length-1;i>=0;i--){
    var f=floaters[i]; f.life-=dt; f.y-=42*dt;
    if(f.life<=0) floaters.splice(i,1);
  }
  bgTimer-=dt;
  if(bgTimer<=0){
    bgTimer=0.35;
    bgHearts.push({x:rand(20,W-20),y:-24,vx:rand(-10,10),vy:rand(18,42),size:rand(14,28),rot:rand(0,3),vr:rand(-0.4,0.4),alpha:rand(0.05,0.11),color:pick(heartColors),seed:rand(0,10)});
  }
  for(i=bgHearts.length-1;i>=0;i--){
    h=bgHearts[i]; h.y+=h.vy*dt; h.x+=h.vx*dt+Math.sin(time+h.seed)*10*dt; h.rot+=h.vr*dt;
    if(h.y>H+36) bgHearts.splice(i,1);
  }
}
function update(dt){
  time+=dt;
  if(gameOver && mode==='demo'){
    demoRestartTimer-=dt; updateParticles(dt);
    if(demoRestartTimer<=0) resetGame();
    return;
  }
  if(gameOver){ updateParticles(dt); return; }

  paddleSquash=Math.max(0,paddleSquash-dt*6);
  shake=Math.max(0,shake-dt*22);
  if(comboTimer>0){ comboTimer-=dt; if(comboTimer<=0){ combo=0; updateHUD(); } }

  var prevPX=paddle.x;
  if(mode==='demo'){ aiMove(dt); }
  else{
    var move=0; if(keys.left) move-=1; if(keys.right) move+=1;
    if(move!==0){ paddle.x+=move*700*dt; mouseTarget=null; }
    else if(mouseTarget!==null){
      var diff=mouseTarget-paddle.x;
      paddle.x+=clamp(diff,-1050*dt,1050*dt);
    }
  }
  paddle.x=clamp(paddle.x,paddle.w/2+10,W-paddle.w/2-10);
  var pVel=dt>0?(paddle.x-prevPX)/dt:0;
  var targetTilt=clamp(pVel*0.00028,-0.16,0.16);
  paddle.tilt+=(targetTilt-paddle.tilt)*Math.min(1,dt*12);

  if(ball.stuck){
    ball.x=paddle.x; ball.y=paddle.y-34;
    ball.stuckTimer-=dt;
    if(ball.stuckTimer<=0){
      ball.stuck=false;
      var ang=rand(-0.35,0.35);
      ball.vx=Math.sin(ang)*ball.speed;
      ball.vy=-Math.cos(ang)*ball.speed;
    }
  }else{
    var steps=2,sdt=dt/steps;
    for(var s=0;s<steps;s++){ if(!ball.stuck && !gameOver) stepBall(sdt); }
    trailTimer-=dt;
    if(trailTimer<=0){
      trailTimer=0.03;
      hearts.push({x:ball.x+rand(-3,3),y:ball.y+rand(-3,3),vx:-ball.vx*0.06+rand(-15,15),vy:rand(10,40),size:rand(5,9),rot:rand(0,3),vr:rand(-3,3),life:0.55,maxLife:0.55,color:pick(['#ff8fab','#ffb3c6','#ff6b9d']),seed:rand(0,10)});
    }
  }
  updateParticles(dt);
}

function drawHamburger(){
  var w=paddle.w, sq=paddleSquash;
  ctx.save();
  ctx.translate(paddle.x,paddle.y);
  ctx.rotate(paddle.tilt);
  ctx.scale(1+sq*0.10,1-sq*0.16);
  // shadow
  ctx.fillStyle='rgba(89,13,34,0.16)';
  ctx.beginPath(); ctx.ellipse(0,18,w*0.46,6,0,0,Math.PI*2); ctx.fill();
  // arms
  ctx.strokeStyle='#e2954a'; ctx.lineWidth=5; ctx.lineCap='round';
  ctx.beginPath(); ctx.moveTo(-w/2+2,2); ctx.lineTo(-w/2-9,9); ctx.stroke();
  ctx.beginPath(); ctx.moveTo(w/2-2,2); ctx.lineTo(w/2+9,9); ctx.stroke();
  ctx.fillStyle='#f2b879';
  ctx.beginPath(); ctx.arc(-w/2-10,10,5,0,Math.PI*2); ctx.fill();
  ctx.beginPath(); ctx.arc(w/2+10,10,5,0,Math.PI*2); ctx.fill();
  // bottom bun
  var gb=ctx.createLinearGradient(0,6,0,20); gb.addColorStop(0,'#f9c784'); gb.addColorStop(1,'#e89b4a');
  ctx.fillStyle=gb; rr(-62,7,124,13,6); ctx.fill();
  ctx.strokeStyle='rgba(120,60,0,0.18)'; ctx.lineWidth=1; ctx.stroke();
  // patty
  var gp=ctx.createLinearGradient(0,0,0,11); gp.addColorStop(0,'#8b4a1f'); gp.addColorStop(1,'#5c2e0d');
  ctx.fillStyle=gp; rr(-60,0,120,11,5); ctx.fill();
  ctx.fillStyle='rgba(0,0,0,0.18)';
  [[-32,5],[0,7],[28,5],[48,7],[-48,7]].forEach(function(p){ ctx.beginPath(); ctx.arc(p[0],p[1],1.6,0,Math.PI*2); ctx.fill(); });
  // cheese
  ctx.fillStyle='#ffc300'; rr(-60,-2,120,7,3); ctx.fill();
  [-38,-12,18,42].forEach(function(x){ rr(x-6,3,12,8,4); ctx.fill(); });
  // lettuce
  ctx.beginPath(); ctx.moveTo(-66,-2);
  for(var x=-66;x<66;x+=22) ctx.quadraticCurveTo(x+11,-7,x+22,-2);
  ctx.lineTo(66,2);
  for(var x2=66;x2>-66;x2-=22) ctx.quadraticCurveTo(x2-11,6,x2-22,2);
  ctx.closePath(); ctx.fillStyle='#57cc4a'; ctx.fill();
  ctx.strokeStyle='#2d9d3f'; ctx.lineWidth=1; ctx.stroke();
  // tomato
  [-32,32].forEach(function(cx){
    ctx.fillStyle='#ff4d6d'; ctx.beginPath(); ctx.ellipse(cx,-4,23,5,0,0,Math.PI*2); ctx.fill();
    ctx.strokeStyle='#d90429'; ctx.lineWidth=1; ctx.stroke();
    ctx.fillStyle='#ff8fa3'; ctx.beginPath(); ctx.ellipse(cx,-4,15,3,0,0,Math.PI*2); ctx.fill();
  });
  // top bun
  var gt=ctx.createLinearGradient(0,-23,0,-4); gt.addColorStop(0,'#ffd8a8'); gt.addColorStop(1,'#f59e42');
  ctx.fillStyle=gt;
  ctx.beginPath(); ctx.moveTo(-62,-6); ctx.quadraticCurveTo(-62,-24,0,-24); ctx.quadraticCurveTo(62,-24,62,-6); ctx.closePath(); ctx.fill();
  ctx.strokeStyle='rgba(120,60,0,0.20)'; ctx.stroke();
  ctx.fillStyle='rgba(255,255,255,0.35)'; ctx.beginPath(); ctx.ellipse(-24,-17,20,5,-0.18,0,Math.PI*2); ctx.fill();
  ctx.fillStyle='#fff3b0';
  [[-42,-14,-0.4],[-20,-20,0.3],[6,-21,-0.2],[30,-19,0.5],[46,-12,0.1],[-46,-9,0.2],[52,-8,-0.3]].forEach(function(s){
    ctx.save(); ctx.translate(s[0],s[1]); ctx.rotate(s[2]);
    ctx.beginPath(); ctx.ellipse(0,0,4.6,2.2,0,0,Math.PI*2); ctx.fill(); ctx.restore();
  });
  // kawaii face
  ctx.fillStyle='#590d22';
  ctx.beginPath(); ctx.arc(-11,-13,3.3,0,Math.PI*2); ctx.fill();
  ctx.beginPath(); ctx.arc(11,-13,3.3,0,Math.PI*2); ctx.fill();
  ctx.fillStyle='white';
  ctx.beginPath(); ctx.arc(-10,-14,1.1,0,Math.PI*2); ctx.fill();
  ctx.beginPath(); ctx.arc(12,-14,1.1,0,Math.PI*2); ctx.fill();
  ctx.strokeStyle='#590d22'; ctx.lineWidth=1.8; ctx.lineCap='round';
  ctx.beginPath(); ctx.arc(0,-11,4,0.15*Math.PI,0.85*Math.PI); ctx.stroke();
  ctx.fillStyle='rgba(255,143,171,0.75)';
  ctx.beginPath(); ctx.ellipse(-19,-9,6,3,0,0,Math.PI*2); ctx.fill();
  ctx.beginPath(); ctx.ellipse(19,-9,6,3,0,0,Math.PI*2); ctx.fill();
  ctx.restore();
}
function drawBall(){
  ctx.save();
  ctx.translate(ball.x,ball.y);
  ctx.rotate(Math.sin(time*10)*0.12+clamp(ball.vx*0.0003,-0.25,0.25));
  heartPath(13);
  var rg=ctx.createRadialGradient(-4,-5,2,0,0,17);
  rg.addColorStop(0,'#ffb3c6'); rg.addColorStop(0.35,'#ff6b9d'); rg.addColorStop(1,'#ff416c');
  ctx.fillStyle=rg; ctx.fill();
  ctx.strokeStyle='#c9184a'; ctx.lineWidth=1.6; ctx.stroke();
  ctx.fillStyle='rgba(255,255,255,0.9)';
  ctx.beginPath(); ctx.ellipse(-5,-4,3.2,2,-0.5,0,Math.PI*2); ctx.fill();
  ctx.restore();
}
function drawBricks(){
  for(var i=0;i<bricks.length;i++){
    var b=bricks[i]; if(!b.alive) continue;
    var c=b.color;
    var grad=ctx.createLinearGradient(b.x,b.y,b.x,b.y+b.h);
    grad.addColorStop(0,c.light); grad.addColorStop(0.5,c.main); grad.addColorStop(1,c.dark);
    ctx.fillStyle=grad; rr(b.x,b.y,b.w,b.h,7); ctx.fill();
    ctx.strokeStyle='rgba(89,13,34,0.18)'; ctx.lineWidth=1; ctx.stroke();
    ctx.fillStyle='rgba(255,255,255,0.28)'; rr(b.x+3,b.y+3,b.w-6,b.h*0.42,5); ctx.fill();
    drawHeart(b.x+b.w/2,b.y+b.h/2+1,6.5,0,'#ffffff',0.9);
    if(b.hp>1){
      ctx.fillStyle='#590d22'; ctx.font='900 11px system-ui,sans-serif'; ctx.textAlign='center'; ctx.textBaseline='middle';
      ctx.fillText('2',b.x+b.w-10,b.y+b.h/2);
    }
  }
}
function draw(){
  var g=ctx.createLinearGradient(0,0,0,H);
  g.addColorStop(0,'#fff5f7'); g.addColorStop(0.55,'#ffe5ec'); g.addColorStop(1,'#ffd6e0');
  ctx.fillStyle=g; ctx.fillRect(0,0,W,H);
  ctx.fillStyle='rgba(255,65,108,0.07)';
  for(var i=0;i<dots.length;i++){ ctx.beginPath(); ctx.arc(dots[i].x,dots[i].y,dots[i].r,0,Math.PI*2); ctx.fill(); }
  // checker tablecloth strip
  var sq=22;
  for(var y=H-28;y<H;y+=sq){
    for(var x=0;x<W;x+=sq){
      if(((x+y)/sq)%2===0){ ctx.fillStyle='rgba(255,65,108,0.06)'; ctx.fillRect(x,y,sq,sq); }
    }
  }
  // walls
  ctx.fillStyle='rgba(255,143,171,0.85)';
  ctx.fillRect(0,0,8,H); ctx.fillRect(W-8,0,8,H); ctx.fillRect(0,0,W,8);

  ctx.save();
  if(shake>0.3) ctx.translate(rand(-shake,shake),rand(-shake,shake));
  var j;
  for(j=0;j<bgHearts.length;j++){ var bh=bgHearts[j]; drawHeart(bh.x,bh.y,bh.size,bh.rot,bh.color,bh.alpha); }
  drawBricks();
  for(j=0;j<hearts.length;j++){ var h=hearts[j]; drawHeart(h.x,h.y,h.size,h.rot,h.color,clamp(h.life/h.maxLife*1.4,0,1)); }
  drawHamburger();
  if(!gameOver) drawBall();
  for(j=0;j<floaters.length;j++){
    var f=floaters[j];
    ctx.save(); ctx.globalAlpha=clamp(f.life/f.max,0,1);
    ctx.font='800 17px system-ui,sans-serif'; ctx.textAlign='center'; ctx.textBaseline='middle';
    ctx.lineWidth=4; ctx.strokeStyle='white'; ctx.strokeText(f.text,f.x,f.y);
    ctx.fillStyle=f.color; ctx.fillText(f.text,f.x,f.y);
    ctx.restore();
  }
  ctx.restore();
}

var last=performance.now();
function loop(now){
  var dt=Math.min(0.033,(now-last)/1000); last=now;
  if(!paused) update(dt);
  draw();
  requestAnimationFrame(loop);
}

// ---------- Events ----------
function canvasX(clientX){
  var r=canvas.getBoundingClientRect();
  return (clientX-r.left)*(W/r.width);
}
canvas.addEventListener('mousemove',function(e){ mouseTarget=canvasX(e.clientX); });
canvas.addEventListener('click',function(){ if(mode==='demo') startGame(); });
canvas.addEventListener('touchstart',function(e){
  e.preventDefault();
  if(mode==='demo') startGame();
  if(e.touches.length) mouseTarget=canvasX(e.touches[0].clientX);
},{passive:false});
canvas.addEventListener('touchmove',function(e){
  e.preventDefault();
  if(e.touches.length) mouseTarget=canvasX(e.touches[0].clientX);
},{passive:false});

overlay.addEventListener('click',function(){ startGame(); });
overlay.addEventListener('touchstart',function(e){ e.preventDefault(); startGame(); },{passive:false});

window.addEventListener('keydown',function(e){
  var k=e.key;
  if(k==='ArrowLeft'||k==='ArrowRight'||k==='ArrowUp'||k==='ArrowDown'||k===' ') e.preventDefault();
  var wasDemo=(mode==='demo');
  if(wasDemo) startGame();
  if(k==='ArrowLeft'||k==='a'||k==='A') keys.left=true;
  if(k==='ArrowRight'||k==='d'||k==='D') keys.right=true;
  if(wasDemo && (k===' '||k==='p'||k==='P'||k==='Escape')) return;
  if(k===' '||k==='p'||k==='P'||k==='Escape'){ if(mode!=='demo') togglePause(); }
  if(k==='Enter' && gameOver && mode!=='demo'){
    overlayEnd.classList.add('hidden'); resetGame(); initAudio();
  }
});
window.addEventListener('keyup',function(e){
  var k=e.key;
  if(k==='ArrowLeft'||k==='a'||k==='A') keys.left=false;
  if(k==='ArrowRight'||k==='d'||k==='D') keys.right=false;
});

pauseBtn.addEventListener('click',function(){
  if(mode==='demo'){ startGame(); return; }
  togglePause();
});
resetBtn.addEventListener('click',function(){
  if(mode==='demo'){ mode='playing'; overlay.classList.add('hidden'); initAudio(); }
  overlayEnd.classList.add('hidden');
  resetGame();
  showToast('New game! 🍔');
});
playAgainBtn.addEventListener('click',function(){
  overlayEnd.classList.add('hidden');
  resetGame(); initAudio();
  showToast('Go go go! 🍔💥');
});

// ---------- Init ----------
buildLevel(1);
resetBall(0);
updateHUD();
spawnHearts(W/2,230,26,1);
requestAnimationFrame(loop);
})();
</script>
</body>
</html>
Reasoning trace (23,363 tokens)
Generating a complete single-file HTML breakout game with inline CSS and JS, hamburger paddle, heart explosion effect, responsive layout, and self-playing demo mode.Adding canvas-drawn hamburger paddle, heart particle bricks, and themed cherry ball with trail.Extending the design with AI demo overlay, responsive canvas layout, and Web Audio sound handling.Refining the ball to a pink heart shape with collision and particle effects.Implementing heart-shaped physics, paddle layers, and ambient background rendering.Adding AI paddle prediction, input handling, and overlay state transitions.Extending CSS layout for responsive sizing and overlay styling with state handling.Adding heart particle systems with caps and substep collision plus scoring and audio handling.Specifying layer order and coordinates for the hamburger drawing stack.Extending the drawing stack with arm and highlight layers and defining brick HP and HUD logic.