Hamburger breakoutOne-line
GPT-6 Luna
by OpenAIReasoningClean
Running live in a sandboxed frame. Click inside it before using the keyboard.
How it went
- Total time
- 35.4 s
- Cost
- $0.0024
- Output tokens
- 4,816
- Spent thinking
- 0 tokens
- Speed
- 146.1 tok/s
- Console errors
- 0
- First token after
- 2.4 s
- First visible text after
- 2.4 s
- Prompt tokens
- 357
- Code size
- 13.8 KB
- Finish reason
- stop
- Served by
- OpenAI
- Model id
openai/gpt-6-luna- Reasoning sent
{"effort":"none"}- Max output
- 64,000 tokens
- Generated
- Nov 10, 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 · 322 lines
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Heartbreak Burger — Breakout</title>
<style>
* { box-sizing: border-box; }
html, body { margin: 0; width: 100%; min-height: 100%; }
body {
min-height: 100vh;
display: grid;
place-items: center;
overflow: hidden;
color: #fff9ee;
font-family: ui-rounded, "Trebuchet MS", system-ui, sans-serif;
background:
radial-gradient(ellipse at 50% 10%, #49306c 0, #241d43 42%, #15152f 100%);
}
.game-shell { width: min(100%, 1040px); padding: 16px; }
.topbar {
display: flex; align-items: center; justify-content: space-between;
gap: 14px; margin: 0 2px 10px;
}
.brand { display: flex; align-items: center; gap: 12px; }
.brand-mark {
display: grid; place-items: center; width: 46px; height: 46px; border-radius: 15px;
background: linear-gradient(145deg, #ff7295, #fa407d);
box-shadow: 0 7px 24px #ff477a55, inset 0 1px #ffffff70;
font-size: 26px;
}
h1 { margin: 0; font-size: clamp(18px, 3vw, 25px); line-height: 1.05; letter-spacing: -.04em; }
.subtitle { margin-top: 4px; color: #c6b9db; font-size: 12px; letter-spacing: .08em; text-transform: uppercase; }
.stats { display: flex; gap: 9px; }
.stat {
min-width: 82px; padding: 8px 13px; border: 1px solid #ffffff1e; border-radius: 13px;
background: #ffffff0b; text-align: center;
}
.stat small { display: block; color: #bdb0d3; font-size: 9px; letter-spacing: .12em; }
.stat strong { display: block; margin-top: 2px; font-size: 16px; }
.board-wrap {
position: relative; overflow: hidden; border: 1px solid #ffffff25; border-radius: 19px;
background: #171831; box-shadow: 0 18px 70px #09091b88, 0 0 0 5px #ffffff05;
}
canvas { display: block; width: 100%; height: auto; aspect-ratio: 1000 / 610; }
.overlay {
position: absolute; inset: 0; display: grid; place-items: center; pointer-events: none;
background: linear-gradient(90deg, #12152b20, transparent 35%, transparent 65%, #12152b20);
transition: opacity .35s ease;
}
.overlay.hidden { opacity: 0; }
.notice {
padding: 15px 22px 14px; border-radius: 18px; border: 1px solid #ffffff40;
background: #201c3de8; box-shadow: 0 8px 34px #09091b77; text-align: center;
backdrop-filter: blur(8px);
}
.notice b { display: block; font-size: clamp(16px, 3vw, 22px); }
.notice span { display: block; margin-top: 5px; color: #d4c7e3; font-size: 12px; }
.footer {
display: flex; justify-content: space-between; gap: 10px; margin: 10px 4px 0;
color: #c5b9d8; font-size: 11px;
}
.footer strong { color: #ff9db7; font-weight: 700; }
@media (max-width: 560px) {
.game-shell { padding: 10px; }
.topbar { align-items: flex-start; }
.brand { gap: 8px; }
.brand-mark { width: 38px; height: 38px; font-size: 22px; border-radius: 12px; }
.stats { gap: 5px; }
.stat { min-width: 57px; padding: 7px 7px; }
.stat small { font-size: 8px; }
.stat strong { font-size: 14px; }
.subtitle { font-size: 9px; }
.footer { font-size: 9px; }
}
</style>
</head>
<body>
<main class="game-shell">
<header class="topbar">
<div class="brand">
<div class="brand-mark">🍔</div>
<div>
<h1>Heartbreak Burger</h1>
<div class="subtitle">Smash bricks. Spread the love.</div>
</div>
</div>
<div class="stats">
<div class="stat"><small>SCORE</small><strong id="score">00000</strong></div>
<div class="stat"><small>HEARTS</small><strong id="hearts">000</strong></div>
<div class="stat"><small>LEVEL</small><strong>01</strong></div>
</div>
</header>
<section class="board-wrap" aria-label="Breakout game">
<canvas id="game" width="1000" height="610"></canvas>
<div class="overlay" id="overlay">
<div class="notice">
<b>🍔 Click or press a key to start</b>
<span>Move your burger with ← → or your mouse</span>
</div>
</div>
</section>
<div class="footer">
<span>Every brick is packed with <strong>tiny love explosions ♥</strong></span>
<span>← → / mouse to move · Space to launch</span>
</div>
</main>
<script>
(() => {
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
const overlay = document.getElementById('overlay');
const scoreEl = document.getElementById('score');
const heartsEl = document.getElementById('hearts');
const W = canvas.width, H = canvas.height;
const colors = ['#ff6e9c','#ff8e78','#ffa94c','#ffd05b','#a78bfa'];
let score = 0, hearts = 0, started = false, demo = true, last = 0, elapsed = 0;
let paddle = { x: W/2, y: H-57, w: 104, h: 40 };
let ball = { x: W/2, y: H-100, vx: 3.6, vy: -4.4, r: 8 };
let bricks = [];
let particles = [];
let keys = {};
let pointerX = null;
let trail = [];
const rows = 5, cols = 10, brickW = 78, brickH = 24, gapX = 12, gapY = 11;
const startX = (W - (cols*brickW + (cols-1)*gapX))/2;
const startY = 91;
function resetBricks() {
bricks = [];
for (let r=0; r<rows; r++) for (let c=0; c<cols; c++) {
bricks.push({x:startX+c*(brickW+gapX), y:startY+r*(brickH+gapY), w:brickW, h:brickH, color:colors[r], alive:true, pulse:Math.random()*6});
}
}
resetBricks();
function heartPath(x,y,size) {
ctx.save(); ctx.translate(x,y); ctx.scale(size/20,size/20);
ctx.beginPath(); ctx.moveTo(0,7);
ctx.bezierCurveTo(-16,-3,-9,-14,0,-6);
ctx.bezierCurveTo(9,-14,16,-3,0,7); ctx.fill(); ctx.restore();
}
function drawHeartBrick(b, time) {
const pulse = 1 + Math.sin(time*2.2+b.pulse)*.035;
ctx.save(); ctx.translate(b.x+b.w/2,b.y+b.h/2); ctx.scale(pulse,pulse);
ctx.shadowColor = b.color; ctx.shadowBlur = 12;
const grad=ctx.createLinearGradient(0,-b.h/2,0,b.h/2);
grad.addColorStop(0, lighten(b.color, 24)); grad.addColorStop(1,b.color);
ctx.fillStyle=grad; rounded(-b.w/2,-b.h/2,b.w,b.h,8); ctx.fill();
ctx.shadowBlur=0;
ctx.strokeStyle='#ffffff70'; ctx.lineWidth=1; rounded(-b.w/2+.7,-b.h/2+.7,b.w-1.4,b.h-1.4,7); ctx.stroke();
ctx.fillStyle='#ffffffb0';
heartPath(0,1,16);
ctx.restore();
}
function lighten(hex, amount) {
const n=parseInt(hex.slice(1),16), r=Math.min(255,(n>>16)+amount), g=Math.min(255,((n>>8)&255)+amount), b=Math.min(255,(n&255)+amount);
return `rgb(${r},${g},${b})`;
}
function rounded(x,y,w,h,r) {
ctx.beginPath(); ctx.roundRect(x,y,w,h,r);
}
function drawBackground(time) {
const bg=ctx.createLinearGradient(0,0,0,H);
bg.addColorStop(0,'#191932'); bg.addColorStop(1,'#20203e');
ctx.fillStyle=bg; ctx.fillRect(0,0,W,H);
ctx.save();
for(let i=0;i<58;i++){
const x=(i*173.3+Math.sin(time*.22+i)*16)%W;
const y=(i*91.7+Math.sin(time*.33+i*2)*13)%H;
ctx.globalAlpha=.15+.2*(.5+.5*Math.sin(time*1.3+i));
ctx.fillStyle=i%3===0?'#ffa6bd':'#d9caff';
ctx.beginPath(); ctx.arc(x,y,i%8===0?1.7:1,0,Math.PI*2); ctx.fill();
}
ctx.globalAlpha=1;
ctx.fillStyle='#ffffff08';
for(let i=0;i<4;i++){
ctx.beginPath(); ctx.ellipse(i*310+85,300,90,250,-.45,0,Math.PI*2); ctx.fill();
}
ctx.restore();
ctx.fillStyle='#ffffff17'; ctx.fillRect(22,24,W-44,1);
ctx.fillStyle='#ffffff17'; ctx.fillRect(22,H-24,W-44,1);
}
function drawBurger(x,y) {
ctx.save(); ctx.translate(x,y);
// soft landing glow
ctx.fillStyle='#ff6d9923'; ctx.beginPath(); ctx.ellipse(0,15,63,16,0,0,Math.PI*2); ctx.fill();
// lower bun
ctx.shadowColor='#ffad52'; ctx.shadowBlur=14;
ctx.fillStyle='#cc6c2c'; rounded(-50,-3,100,19,9); ctx.fill();
ctx.shadowBlur=0;
ctx.fillStyle='#ffcf74'; rounded(-46,-7,92,17,8); ctx.fill();
// lettuce frill
ctx.fillStyle='#58c983'; ctx.beginPath(); ctx.moveTo(-47,-10);
for(let i=0;i<=10;i++){let x=-47+i*9.4;ctx.lineTo(x,-10+(i%2?5:0));}
ctx.lineTo(47,-13); ctx.lineTo(-47,-13); ctx.closePath(); ctx.fill();
// tomato and cheese
ctx.fillStyle='#ef5967'; rounded(-41,-18,82,9,4); ctx.fill();
ctx.fillStyle='#ffc74b'; ctx.beginPath(); ctx.moveTo(-45,-20);ctx.lineTo(40,-20);ctx.lineTo(33,-12);ctx.lineTo(26,-16);ctx.lineTo(17,-11);ctx.lineTo(-45,-13);ctx.closePath();ctx.fill();
// patty
ctx.fillStyle='#6b382b'; rounded(-43,-24,86,9,5);ctx.fill();
// top bun
ctx.shadowColor='#ffcf74';ctx.shadowBlur=12;
ctx.fillStyle='#e99a44';ctx.beginPath();ctx.moveTo(-44,-23);ctx.bezierCurveTo(-42,-49,-27,-55,0,-55);ctx.bezierCurveTo(27,-55,42,-49,44,-23);ctx.closePath();ctx.fill();
ctx.shadowBlur=0;
const seeds=[[-23,-39],[-9,-46],[9,-46],[24,-39],[-3,-34],[15,-32]];
ctx.fillStyle='#fff0bc';
seeds.forEach(([sx,sy])=>{ctx.save();ctx.translate(sx,sy);ctx.rotate(-.5);ctx.beginPath();ctx.ellipse(0,0,2,4,0,0,Math.PI*2);ctx.fill();ctx.restore();});
// glossy bun highlight
ctx.strokeStyle='#ffd691';ctx.lineWidth=2;ctx.beginPath();ctx.arc(-2,-30,31,3.6,5.2);ctx.stroke();
ctx.restore();
}
function makeBurst(x,y,color) {
const count=26+Math.floor(Math.random()*14);
for(let i=0;i<count;i++){
const a=Math.random()*Math.PI*2, speed=1.1+Math.random()*4;
particles.push({x,y,vx:Math.cos(a)*speed,vy:Math.sin(a)*speed-1.2,life:45+Math.random()*35,max:80,size:5+Math.random()*8,color:Math.random()<.78?'#ff719b':color,spin:(Math.random()-.5)*.14,rot:Math.random()*6.28});
}
for(let i=0;i<8;i++) particles.push({x,y,vx:(Math.random()-.5)*5,vy:(Math.random()-.5)*5,life:24,max:24,size:2+Math.random()*3,color:'#fff0aa',spark:true});
}
function updateParticles(dt) {
const step=dt/16.67;
for(let i=particles.length-1;i>=0;i--){
let p=particles[i];p.x+=p.vx*step;p.y+=p.vy*step;p.vy+=.055*step;p.vx*=.991;p.life-=step;p.rot+=p.spin*step;
if(p.life<=0)particles.splice(i,1);
}
}
function drawParticles() {
particles.forEach(p=>{
ctx.globalAlpha=Math.max(0,p.life/p.max);
if(p.spark){ctx.fillStyle=p.color;ctx.beginPath();ctx.arc(p.x,p.y,p.size,0,Math.PI*2);ctx.fill();}
else{ctx.fillStyle=p.color;heartPath(p.x,p.y,p.size);}
});
ctx.globalAlpha=1;
}
function moveBall(dt) {
const s=dt/16.67;
ball.x+=ball.vx*s; ball.y+=ball.vy*s;
if(ball.x<ball.r+25){ball.x=ball.r+25;ball.vx=Math.abs(ball.vx);}
if(ball.x>W-ball.r-25){ball.x=W-ball.r-25;ball.vx=-Math.abs(ball.vx);}
if(ball.y<45){ball.y=45;ball.vy=Math.abs(ball.vy);}
// paddle collision
if(ball.vy>0 && ball.y+ball.r>=paddle.y-17 && ball.y<paddle.y+8 && Math.abs(ball.x-paddle.x)<paddle.w/2+ball.r){
ball.y=paddle.y-18; let offset=(ball.x-paddle.x)/(paddle.w/2);
ball.vx=offset*5.8; ball.vy=-Math.max(4.2,Math.sqrt(43-ball.vx*ball.vx));
makeBurst(ball.x,paddle.y-19,'#ffcb69');
}
for(const b of bricks){
if(!b.alive)continue;
if(ball.x+ball.r>b.x&&ball.x-ball.r<b.x+b.w&&ball.y+ball.r>b.y&&ball.y-ball.r<b.y+b.h){
b.alive=false; score+=100; hearts+=34; makeBurst(ball.x,ball.y,b.color);
scoreEl.textContent=String(score).padStart(5,'0'); heartsEl.textContent=String(hearts).padStart(3,'0');
const overlapX=Math.min(ball.x+ball.r-b.x,b.x+b.w-(ball.x-ball.r));
const overlapY=Math.min(ball.y+ball.r-b.y,b.y+b.h-(ball.y-ball.r));
if(overlapX<overlapY)ball.vx*=-1;else ball.vy*=-1;
break;
}
}
if(ball.y>H+30){ball.x=paddle.x;ball.y=paddle.y-80;ball.vx=(Math.random()-.5)*4;ball.vy=-4.6;}
if(bricks.every(b=>!b.alive)){resetBricks();ball.vy=-Math.abs(ball.vy);score+=500;scoreEl.textContent=String(score).padStart(5,'0');}
}
function drawBall(time) {
trail.unshift({x:ball.x,y:ball.y}); if(trail.length>7)trail.pop();
trail.forEach((p,i)=>{ctx.globalAlpha=(1-i/trail.length)*.18;ctx.fillStyle='#fff4d9';ctx.beginPath();ctx.arc(p.x,p.y,ball.r*(1-i*.08),0,Math.PI*2);ctx.fill();});
ctx.globalAlpha=1;
ctx.save();ctx.shadowColor='#ffe6a4';ctx.shadowBlur=18;
const g=ctx.createRadialGradient(ball.x-3,ball.y-4,1,ball.x,ball.y,ball.r+2);
g.addColorStop(0,'#fffde7');g.addColorStop(.48,'#ffe681');g.addColorStop(1,'#ff8e63');
ctx.fillStyle=g;ctx.beginPath();ctx.arc(ball.x,ball.y,ball.r,0,Math.PI*2);ctx.fill();ctx.restore();
}
function draw(time) {
drawBackground(time);
// small board labels
ctx.font='700 10px ui-rounded, system-ui';ctx.fillStyle='#9f91b8';ctx.textAlign='left';ctx.fillText('LOVE BLOCKS',31,48);
ctx.textAlign='right';ctx.fillText('♥ 100% FRESH',W-31,48);
bricks.forEach(b=>{if(b.alive)drawHeartBrick(b,time);});
drawParticles();
drawBurger(paddle.x,paddle.y);
drawBall(time);
}
function startGame() {
if(started)return;
started=true;demo=false;overlay.classList.add('hidden');
ball.vx=3.6;ball.vy=-4.4;
}
function inputStart(){if(!started)startGame();}
window.addEventListener('keydown',e=>{
if(['ArrowLeft','ArrowRight',' ','a','d','A','D'].includes(e.key))e.preventDefault();
keys[e.key]=true;inputStart();
});
window.addEventListener('keyup',e=>keys[e.key]=false);
canvas.addEventListener('pointermove',e=>{
const rect=canvas.getBoundingClientRect();pointerX=(e.clientX-rect.left)*W/rect.width;
if(!started) startGame();
});
canvas.addEventListener('pointerdown',inputStart);
function tick(now) {
if(!last)last=now;
const dt=Math.min(34,now-last); last=now; elapsed+=dt/1000;
if(started){
if(pointerX!==null) paddle.x+=(pointerX-paddle.x)*.2;
else {
if(keys.ArrowLeft||keys.a||keys.A)paddle.x-=8;
if(keys.ArrowRight||keys.d||keys.D)paddle.x+=8;
}
} else {
// Self-playing attract mode: track the ball with gentle anticipation.
const target=ball.x+ball.vx*7;
paddle.x+=(target-paddle.x)*.065;
if(Math.sin(elapsed*1.4)>0.97) paddle.x+=(Math.random()-.5)*2;
}
paddle.x=Math.max(25+paddle.w/2,Math.min(W-25-paddle.w/2,paddle.x));
moveBall(dt);
updateParticles(dt);
draw(elapsed);
requestAnimationFrame(tick);
}
requestAnimationFrame(tick);
})();
</script>
</body>
</html>