Hamburger breakoutOne-line
GPT-6.1 Terra
by OpenAIReasoningClean
Running live in a sandboxed frame. Click inside it before using the keyboard.
How it went
- Total time
- 2 min 25 s
- Cost
- $0.061
- Output tokens
- 12,103
- Spent thinking
- 3,567 tokens
- Speed
- 91 tok/s
- Console errors
- 0
- First token after
- 11.6 s
- First visible text after
- 1 min 8 s
- Prompt tokens
- 357
- Code size
- 23.2 KB
- Finish reason
- stop
- Served by
- OpenAI
- Model id
openai/gpt-6.1-terra- Reasoning sent
{"effort":"high"}- Max output
- 128,000 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 · 443 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Heart Breaker</title>
<style>
:root {
--bg: #161626;
--panel: #222238;
--line: #414058;
--cream: #fff4db;
--muted: #aaa4b8;
--pink: #ff7799;
--yellow: #ffd784;
}
* { box-sizing: border-box; }
html, body { margin: 0; min-height: 100%; }
body {
color: var(--cream);
font-family: "Trebuchet MS", "Arial Rounded MT Bold", Arial, sans-serif;
background:
radial-gradient(ellipse at 15% 18%, rgba(105, 54, 100, .2), transparent 30%),
radial-gradient(ellipse at 87% 76%, rgba(74, 61, 113, .2), transparent 34%),
var(--bg);
}
body::before {
content: "";
position: fixed;
inset: 0;
pointer-events: none;
opacity: .24;
background-image: radial-gradient(#b6a3c0 1px, transparent 1px);
background-size: 42px 42px;
mask-image: linear-gradient(to bottom, transparent, #000 20%, #000 80%, transparent);
}
.wrap { position: relative; width: min(1100px, calc(100% - 48px)); margin: 0 auto; }
header {
height: 78px;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid rgba(255,255,255,.09);
}
.brand { display: flex; align-items: center; gap: 10px; }
.brand-icon {
width: 36px; height: 36px; border-radius: 11px;
background: var(--pink); display: grid; place-items: center;
box-shadow: 0 3px 0 #bd4c6d;
}
.brand-name { font-weight: 900; font-size: 13px; letter-spacing: .09em; line-height: 1.1; }
.brand-name small { display: block; color: #b3a9ba; font-size: 9px; letter-spacing: .18em; margin-top: 4px; }
.header-right { display: flex; align-items: center; gap: 15px; color: #a8a0b3; font-size: 10px; font-weight: bold; letter-spacing: .14em; }
.online { border: 1px solid #454154; border-radius: 30px; padding: 8px 11px; color: #d8ced5; }
.online::before { content: ""; display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: #a9e9aa; margin-right: 7px; box-shadow: 0 0 8px #a9e9aa; }
.heading { height: 92px; display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.eyebrow { color: #ff9cb0; font-size: 10px; letter-spacing: .18em; font-weight: 900; margin-bottom: 5px; }
h1 { margin: 0; font-size: clamp(27px, 3vw, 38px); letter-spacing: -.055em; line-height: 1; font-weight: 1000; }
h1 span { color: var(--pink); }
.heading-note { color: #b2a9b9; font-size: 12px; line-height: 1.5; text-align: right; }
.heading-note strong { display: block; color: #f7dcb9; font-size: 11px; letter-spacing: .08em; }
.layout { display: grid; grid-template-columns: minmax(0, 1fr) 222px; gap: 16px; align-items: stretch; }
.game-shell {
overflow: hidden; border: 1px solid #4b465c; border-radius: 15px;
background: #24233a; box-shadow: 0 12px 0 rgba(8,8,17,.17), 0 24px 60px rgba(0,0,0,.2);
}
.scorebar { height: 62px; display: flex; align-items: center; justify-content: space-between; padding: 0 22px; }
.score-group { display: flex; align-items: center; gap: 12px; }
.score-icon {
display: grid; place-items: center; width: 33px; height: 33px;
color: #ffcf83; border-radius: 9px; background: #393143; font-size: 17px;
}
.stat-label { color: #a69aaa; font-size: 9px; font-weight: 900; letter-spacing: .16em; line-height: 1; }
.score-value { margin-top: 5px; font-family: monospace; font-size: 19px; line-height: 1; font-weight: 900; letter-spacing: .06em; color: #fff4dc; }
.level { border: 1px solid #52475c; background: #302a3d; color: #e7c4c5; border-radius: 30px; padding: 7px 12px; font-size: 10px; font-weight: 900; letter-spacing: .1em; }
.level span { color: #ffca7c; margin-right: 4px; }
.lives { text-align: right; }
.life-icons { margin-top: 4px; font-size: 18px; line-height: 1; letter-spacing: 2px; color: #ff829d; white-space: nowrap; }
.life-icons .lost { color: #554555; }
.field { position: relative; background: #191b2c; cursor: crosshair; touch-action: none; }
canvas { display: block; width: 100%; height: auto; aspect-ratio: 5 / 3; }
.start-hint {
position: absolute; top: 43%; left: 50%; transform: translate(-50%, -50%);
white-space: nowrap; pointer-events: none; text-align: center;
padding: 10px 16px; border: 1px solid rgba(255,194,207,.35); border-radius: 10px;
color: #fff2e8; background: rgba(40, 34, 52, .92); box-shadow: 0 7px 20px #10101d66;
font-size: 11px; font-weight: bold; letter-spacing: .025em;
}
.start-hint b { color: #ff93ac; font-size: 9px; letter-spacing: .13em; margin-right: 9px; }
.start-hint.hidden { display: none; }
aside { display: flex; flex-direction: column; gap: 12px; }
.card { background: rgba(36, 35, 55, .94); border: 1px solid #464154; border-radius: 14px; padding: 16px; }
.card-label { color: #b5a6b5; font-weight: 900; font-size: 9px; letter-spacing: .16em; }
.special { position: relative; overflow: hidden; text-align: center; padding: 16px 14px 15px; background: #302738; }
.special .card-label { text-align: left; color: #e1a6b2; }
.special .number { float: right; color: #f9ca9a; }
.burger-art { display: block; width: 140px; height: 99px; margin: 8px auto 2px; }
.special h2 { margin: 1px 0 4px; font-size: 19px; letter-spacing: -.04em; }
.special p { color: #c4aeb7; font-size: 11px; line-height: 1.45; margin: 0; }
.controls h3, .progress-card h3 { margin: 0 0 13px; font-size: 12px; letter-spacing: .06em; }
.control-row { display: flex; gap: 10px; align-items: center; margin-top: 12px; }
.keys { display: flex; gap: 3px; flex-shrink: 0; }
kbd, .mouse-icon {
display: grid; place-items: center; width: 26px; height: 27px;
border: 1px solid #62576a; border-bottom-width: 3px; border-radius: 5px;
background: #383347; color: #ffe7da; font: bold 13px Arial, sans-serif;
}
.mouse-icon { width: 55px; font-size: 15px; color: #ffc994; }
.control-copy { color: #b9afbd; font-size: 10px; line-height: 1.35; }
.control-copy strong { color: #f4e5db; display: block; font-size: 11px; }
.control-foot { border-top: 1px solid #494153; margin-top: 14px; padding-top: 11px; color: #a99cab; font-size: 10px; line-height: 1.45; }
.control-foot span { color: #ff8da4; }
.progress-card { flex: 1; min-height: 95px; }
.progress-top { display: flex; justify-content: space-between; align-items: center; gap: 5px; }
.progress-top h3 { margin: 0; }
.progress-number { font-family: monospace; color: #ff9caf; font-size: 12px; font-weight: bold; }
.track { height: 7px; border-radius: 7px; background: #484053; margin: 15px 0 8px; overflow: hidden; }
.fill { height: 100%; width: 0%; border-radius: inherit; background: linear-gradient(90deg, #ff7697, #ffbe91); transition: width .25s; }
.progress-card p { color: #a99eae; font-size: 10px; margin: 0; }
footer { display: flex; justify-content: space-between; padding: 16px 2px 22px; color: #847b8f; font-size: 9px; font-weight: bold; letter-spacing: .13em; }
footer span { color: #ff8da4; }
@media (max-width: 760px) {
.wrap { width: min(100% - 28px, 560px); }
header { height: 65px; }
.header-right > span:first-child { display: none; }
.heading { height: 85px; }
.heading-note { font-size: 10px; }
.heading-note strong { font-size: 9px; }
.layout { grid-template-columns: 1fr; }
aside { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.special { grid-row: span 2; }
.burger-art { width: 115px; height: 75px; }
.controls { padding: 13px; }
.control-row { margin-top: 8px; }
.control-foot { margin-top: 9px; padding-top: 8px; }
.progress-card { padding: 13px; min-height: 0; }
.track { margin: 10px 0 7px; }
footer { padding-top: 14px; }
}
@media (max-width: 440px) {
.heading-note { max-width: 110px; }
.scorebar { height: 55px; padding: 0 11px; }
.score-group { gap: 7px; }
.score-icon { width: 28px; height: 28px; }
.score-value { font-size: 16px; }
.level { font-size: 8px; padding: 7px; }
.life-icons { font-size: 15px; letter-spacing: 0; }
.start-hint { font-size: 9px; padding: 8px 10px; }
.start-hint b { font-size: 8px; margin-right: 5px; }
.card { border-radius: 11px; }
.special h2 { font-size: 17px; }
footer { font-size: 8px; }
}
</style>
</head>
<body>
<div class="wrap">
<header>
<div class="brand">
<div class="brand-icon">
<svg width="21" height="20" viewBox="0 0 24 24" aria-hidden="true"><path fill="#fff1df" d="M12 21s-8.7-5.3-9.7-11.1C1.4 5.4 4.3 3 7.3 3c2 0 3.7 1.1 4.7 2.7C13 4.1 14.7 3 16.7 3c3 0 5.9 2.4 5 6.9C20.7 15.7 12 21 12 21Z"/></svg>
</div>
<div class="brand-name">LOVE BUN<small>ARCADE CLUB</small></div>
</div>
<div class="header-right"><span>GOOD FOOD. GREAT GAMES.</span><span class="online">ARCADE IS OPEN</span></div>
</header>
<div class="heading">
<div><div class="eyebrow">✦ SERVING UP A LITTLE JOY</div><h1>HEART <span>BREAKER.</span></h1></div>
<div class="heading-note"><strong>THE CUTEST BREAKOUT IN TOWN</strong>Smash bricks. Spread love. Repeat.</div>
</div>
<main class="layout">
<section class="game-shell" aria-label="Heart Breaker game">
<div class="scorebar">
<div class="score-group"><div class="score-icon">✦</div><div><div class="stat-label">YOUR SCORE</div><div class="score-value" id="score">000000</div></div></div>
<div class="level"><span>★</span> LEVEL <span id="level">01</span></div>
<div class="lives"><div class="stat-label">LIVES</div><div class="life-icons" id="lives">♥ ♥ ♥</div></div>
</div>
<div class="field" id="field">
<canvas id="game" width="900" height="540" aria-label="Breakout game with a hamburger paddle"></canvas>
<div class="start-hint" id="hint"><b>✦ DEMO MODE</b> Click or press a key to start</div>
</div>
</section>
<aside>
<section class="card special">
<div class="card-label">TODAY'S SPECIAL <span class="number">NO. 01</span></div>
<svg class="burger-art" viewBox="0 0 160 110" aria-hidden="true">
<path d="M18 38l3-7 3 7 7 3-7 3-3 7-3-7-7-3zM137 18l2-5 2 5 5 2-5 2-2 5-2-5-5-2z" fill="#ffc879"/>
<path d="M129 46c-8-5-12 2-7 7l7 6 7-6c5-5 1-12-7-7z" fill="#ff829f"/>
<ellipse cx="80" cy="96" rx="54" ry="7" fill="#211c2b" opacity=".45"/>
<path d="M30 78h100v7c0 8-6 11-14 11H44c-8 0-14-3-14-11z" fill="#e8a34f" stroke="#713f37" stroke-width="3"/>
<path d="M27 68c-3-4 0-8 5-8h96c5 0 8 4 5 8l-5 8H32z" fill="#8d4a39" stroke="#713f37" stroke-width="3"/>
<path d="M28 63l12-5 10 5 10-5 10 5 10-5 10 5 10-5 10 5 10-5 12 5-5 8H33z" fill="#a8d977" stroke="#568352" stroke-width="2"/>
<path d="M56 68h48L89 81l-9-9-9 9z" fill="#ffcf55"/>
<path d="M29 58c0-24 20-40 51-40s51 16 51 40c0 5-4 8-9 8H38c-5 0-9-3-9-8z" fill="#f5b45e" stroke="#8b503c" stroke-width="3"/>
<path d="M39 47c5-14 20-23 38-24" fill="none" stroke="#ffdc9b" stroke-width="4" stroke-linecap="round"/>
<g fill="#fff0be"><ellipse cx="57" cy="38" rx="3" ry="1.5" transform="rotate(-25 57 38)"/><ellipse cx="79" cy="31" rx="3" ry="1.5" transform="rotate(20 79 31)"/><ellipse cx="103" cy="38" rx="3" ry="1.5" transform="rotate(-20 103 38)"/></g>
<circle cx="69" cy="53" r="2.4" fill="#63443c"/><circle cx="91" cy="53" r="2.4" fill="#63443c"/>
<path d="M76 57q4 4 8 0" fill="none" stroke="#63443c" stroke-width="2" stroke-linecap="round"/>
<circle cx="61" cy="58" r="3.5" fill="#f48683" opacity=".6"/><circle cx="99" cy="58" r="3.5" fill="#f48683" opacity=".6"/>
</svg>
<h2>THE LOVE BUN</h2>
<p>One extra-cute paddle,<br>with a side of chaos.</p>
</section>
<section class="card controls">
<h3>HOW TO PLAY <span style="color:#ff91a8">✳</span></h3>
<div class="control-row"><div class="keys"><kbd>←</kbd><kbd>→</kbd></div><div class="control-copy"><strong>Move the bun</strong>Use arrow keys</div></div>
<div class="control-row"><div class="mouse-icon">↔</div><div class="control-copy"><strong>Or use your mouse</strong>Touch works too!</div></div>
<div class="control-foot"><span>♥</span> Keep the ball up and break<br> every last brick.</div>
</section>
<section class="card progress-card">
<div class="progress-top"><h3>BRICKS BUSTED</h3><div class="progress-number" id="count">00 / 55</div></div>
<div class="track"><div class="fill" id="fill"></div></div>
<p>Every brick is full of love. ♥</p>
</section>
</aside>
</main>
<footer><div>MADE WITH <span>♥</span> AND A LITTLE BIT OF KETCHUP</div><div>EST. JUST FOR YOU ✦</div></footer>
</div>
<script>
(() => {
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
const field = document.getElementById('field');
const hint = document.getElementById('hint');
const scoreEl = document.getElementById('score');
const levelEl = document.getElementById('level');
const livesEl = document.getElementById('lives');
const countEl = document.getElementById('count');
const fillEl = document.getElementById('fill');
const W = 900, H = 540, cols = 11, rows = 5;
const colors = ['#ff88a4', '#ffa18f', '#ffc68d', '#f8dd95', '#c9b4e9'];
const particles = [];
const keys = new Set();
const paddle = { x: 450, y: 479, w: 132 };
const ball = { x: 450, y: 245, vx: 110, vy: -305, r: 8 };
let bricks = [], score = 0, lives = 3, level = 1, broken = 0;
let demo = true, gameOver = false, last = 0, time = 0;
function makeBricks() {
bricks = [];
const gap = 8, margin = 36, bw = (W - margin * 2 - gap * (cols - 1)) / cols;
for (let r = 0; r < rows; r++) {
for (let c = 0; c < cols; c++) {
bricks.push({ x: margin + c * (bw + gap), y: 34 + r * 31, w: bw, h: 23, color: colors[r], alive: true });
}
}
broken = 0;
updateUI();
}
function updateUI() {
scoreEl.textContent = String(score).padStart(6, '0');
levelEl.textContent = String(level).padStart(2, '0');
livesEl.innerHTML = Array.from({length: 3}, (_, i) => `<span class="${i >= lives ? 'lost' : ''}">♥</span>`).join(' ');
countEl.textContent = String(broken).padStart(2, '0') + ' / 55';
fillEl.style.width = (broken / 55 * 100) + '%';
}
function resetBall() {
ball.x = 450; ball.y = 245; ball.vx = 110 * (Math.random() < .5 ? -1 : 1); ball.vy = -305;
paddle.x = 450;
}
function startGame() {
if (!demo && !gameOver) return;
demo = false; gameOver = false; score = 0; lives = 3; level = 1;
particles.length = 0; makeBricks(); resetBall();
hint.classList.add('hidden');
updateUI();
}
function heart(x, y, s, color, alpha = 1, rotation = 0) {
ctx.save(); ctx.translate(x, y); ctx.rotate(rotation); ctx.scale(s, s);
ctx.globalAlpha = alpha; ctx.fillStyle = color;
ctx.beginPath();
ctx.moveTo(0, .85);
ctx.bezierCurveTo(-.15, .68, -1, .14, -1, -.35);
ctx.bezierCurveTo(-1, -.9, -.3, -1.05, 0, -.55);
ctx.bezierCurveTo(.3, -1.05, 1, -.9, 1, -.35);
ctx.bezierCurveTo(1, .14, .15, .68, 0, .85);
ctx.fill(); ctx.restore();
}
function burst(x, y, color) {
const palette = [color, '#ff789b', '#ffb6c3', '#ffe2a5', '#fff0e4', '#f8a6ce'];
for (let i = 0; i < 48; i++) {
const a = Math.random() * Math.PI * 2;
const speed = 45 + Math.random() * 195;
particles.push({
x, y, vx: Math.cos(a) * speed, vy: Math.sin(a) * speed - 45,
size: 2.5 + Math.random() * 5, life: 1.4 + Math.random() * 1.1,
age: 0, color: palette[Math.floor(Math.random() * palette.length)],
rot: Math.random() * 6.28, spin: (Math.random() - .5) * 5
});
}
}
function rounded(x, y, w, h, r, fill) {
ctx.fillStyle = fill; ctx.beginPath(); ctx.roundRect(x, y, w, h, r); ctx.fill();
}
function drawBackground() {
ctx.fillStyle = '#1b1c2e'; ctx.fillRect(0, 0, W, H);
const grad = ctx.createRadialGradient(450, 220, 20, 450, 240, 550);
grad.addColorStop(0, 'rgba(74,53,83,.20)'); grad.addColorStop(1, 'rgba(15,16,28,.22)');
ctx.fillStyle = grad; ctx.fillRect(0, 0, W, H);
ctx.strokeStyle = 'rgba(255,255,255,.025)'; ctx.lineWidth = 1;
for (let x = 0; x < W; x += 45) { ctx.beginPath(); ctx.moveTo(x, 0); ctx.lineTo(x, H); ctx.stroke(); }
for (let y = 0; y < H; y += 45) { ctx.beginPath(); ctx.moveTo(0, y); ctx.lineTo(W, y); ctx.stroke(); }
const stars = [[23,211,3],[867,225,4],[50,340,3],[837,350,3],[154,262,2],[752,275,2],[285,390,2],[664,397,2],[30,445,2],[874,438,2]];
ctx.strokeStyle = 'rgba(255,213,180,.23)';
stars.forEach(([x,y,s]) => { ctx.beginPath(); ctx.moveTo(x-s,y); ctx.lineTo(x+s,y); ctx.moveTo(x,y-s); ctx.lineTo(x,y+s); ctx.stroke(); });
ctx.strokeStyle = 'rgba(255,255,255,.08)'; ctx.setLineDash([4, 7]);
ctx.beginPath(); ctx.moveTo(36, 461); ctx.lineTo(864, 461); ctx.stroke(); ctx.setLineDash([]);
ctx.font = 'bold 10px monospace'; ctx.fillStyle = 'rgba(231,200,202,.35)';
ctx.fillText('LOVE BUN ARCADE / 01', 36, 522);
ctx.textAlign = 'right'; ctx.fillText('GOOD LUCK, CUTIE!', 864, 522); ctx.textAlign = 'left';
}
function drawBricks() {
for (const b of bricks) {
if (!b.alive) continue;
rounded(b.x, b.y + 3, b.w, b.h, 5, 'rgba(0,0,0,.25)');
rounded(b.x, b.y, b.w, b.h, 5, b.color);
ctx.fillStyle = 'rgba(255,255,255,.25)';
ctx.beginPath(); ctx.roundRect(b.x + 5, b.y + 4, b.w - 10, 3, 2); ctx.fill();
heart(b.x + b.w / 2, b.y + 14, 4, '#fff7e7', .38);
}
}
function drawPaddle() {
const x = paddle.x - paddle.w / 2, y = paddle.y, w = paddle.w;
ctx.save();
ctx.shadowColor = 'rgba(0,0,0,.35)'; ctx.shadowBlur = 12; ctx.shadowOffsetY = 5;
rounded(x + 7, y + 28, w - 14, 14, 7, '#df9449');
ctx.restore();
rounded(x + 3, y + 23, w - 6, 11, 5, '#783e35');
ctx.fillStyle = '#9dcf70'; ctx.beginPath(); ctx.moveTo(x + 3, y + 23);
for (let i = 0; i <= 12; i++) ctx.lineTo(x + 3 + i * (w - 6) / 12, y + 20 + (i % 2 ? 4 : 0));
ctx.lineTo(x + w - 3, y + 25); ctx.lineTo(x + 3, y + 25); ctx.closePath(); ctx.fill();
ctx.fillStyle = '#ffca59'; ctx.beginPath(); ctx.moveTo(x + 43,y + 26); ctx.lineTo(x + 83,y + 26); ctx.lineTo(x + 72,y + 34); ctx.lineTo(x + 63,y + 28); ctx.lineTo(x + 54,y + 34); ctx.closePath(); ctx.fill();
const bun = ctx.createLinearGradient(0, y, 0, y + 23); bun.addColorStop(0, '#ffd28b'); bun.addColorStop(1, '#eea857');
ctx.fillStyle = bun; ctx.beginPath(); ctx.moveTo(x + 5, y + 19);
ctx.bezierCurveTo(x + 9, y - 7, x + w - 9, y - 7, x + w - 5, y + 19);
ctx.quadraticCurveTo(x + w - 5, y + 23, x + w - 12, y + 23);
ctx.lineTo(x + 12, y + 23); ctx.quadraticCurveTo(x + 5, y + 23, x + 5, y + 19); ctx.fill();
ctx.fillStyle = '#fff0c0';
[[32,11,-.4],[48,5,.3],[68,8,-.3],[87,5,.4],[102,12,-.3]].forEach(([sx,sy,a]) => {
ctx.save(); ctx.translate(x + sx, y + sy); ctx.rotate(a); ctx.beginPath(); ctx.ellipse(0,0,3,1.3,0,0,Math.PI*2); ctx.fill(); ctx.restore();
});
ctx.fillStyle = '#75483c'; ctx.beginPath(); ctx.arc(x + 57, y + 17, 2, 0, Math.PI*2); ctx.arc(x + 75, y + 17, 2, 0, Math.PI*2); ctx.fill();
ctx.strokeStyle = '#75483c'; ctx.lineWidth = 1.5; ctx.lineCap = 'round'; ctx.beginPath(); ctx.arc(x + 66, y + 17, 3, .2, Math.PI - .2); ctx.stroke();
}
function drawBall() {
ctx.save(); ctx.shadowBlur = 18; ctx.shadowColor = '#ff9eb6';
ctx.fillStyle = '#fff7e9'; ctx.beginPath(); ctx.arc(ball.x, ball.y, ball.r, 0, Math.PI*2); ctx.fill(); ctx.restore();
ctx.fillStyle = '#ffc1cc'; ctx.beginPath(); ctx.arc(ball.x + 2, ball.y + 2, 3, 0, Math.PI*2); ctx.fill();
ctx.fillStyle = '#fff'; ctx.beginPath(); ctx.arc(ball.x - 2, ball.y - 3, 2, 0, Math.PI*2); ctx.fill();
}
function drawParticles() {
for (const p of particles) {
const alpha = Math.min(1, (p.life - p.age) / .6);
heart(p.x, p.y, p.size, p.color, Math.max(0, alpha), p.rot);
}
}
function update(dt) {
time += dt;
if (demo) {
const target = Math.max(paddle.w / 2 + 8, Math.min(W - paddle.w / 2 - 8, ball.x + ball.vx * .09));
paddle.x += Math.max(-540 * dt, Math.min(540 * dt, target - paddle.x));
} else if (!gameOver) {
if (keys.has('ArrowLeft') || keys.has('a') || keys.has('A')) paddle.x -= 550 * dt;
if (keys.has('ArrowRight') || keys.has('d') || keys.has('D')) paddle.x += 550 * dt;
}
paddle.x = Math.max(paddle.w / 2 + 8, Math.min(W - paddle.w / 2 - 8, paddle.x));
if (!gameOver) {
const oldY = 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); }
if (ball.x > W - ball.r - 8) { ball.x = W - ball.r - 8; ball.vx = -Math.abs(ball.vx); }
if (ball.y < ball.r + 8) { ball.y = ball.r + 8; ball.vy = Math.abs(ball.vy); }
for (const b of bricks) {
if (!b.alive || 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) continue;
b.alive = false; broken++; score += 100;
burst(b.x + b.w / 2, b.y + b.h / 2, b.color);
if (oldY - ball.r >= b.y + b.h || oldY + ball.r <= b.y) ball.vy *= -1;
else ball.vx *= -1;
updateUI();
if (broken === rows * cols) { level++; makeBricks(); resetBall(); }
break;
}
if (ball.vy > 0 && oldY + ball.r <= paddle.y + 4 && ball.y + ball.r >= paddle.y && Math.abs(ball.x - paddle.x) < paddle.w / 2 + ball.r) {
const hit = Math.max(-1, Math.min(1, (ball.x - paddle.x) / (paddle.w / 2)));
const speed = Math.min(440, Math.hypot(ball.vx, ball.vy) + 2);
ball.vx = hit * speed * .82;
ball.vy = -Math.sqrt(speed * speed - ball.vx * ball.vx);
ball.y = paddle.y - ball.r;
}
if (ball.y > H + 15) {
if (demo) resetBall();
else {
lives--; updateUI();
if (lives <= 0) {
gameOver = true;
hint.innerHTML = '<b>♥ GAME OVER</b> Click or press a key to play again';
hint.classList.remove('hidden');
} else resetBall();
}
}
}
for (let i = particles.length - 1; i >= 0; i--) {
const p = particles[i]; p.age += dt;
if (p.age >= p.life) { particles.splice(i, 1); continue; }
p.x += p.vx * dt; p.y += p.vy * dt; p.vy += 150 * dt;
p.vx *= Math.pow(.88, dt); p.rot += p.spin * dt;
}
}
function frame(timestamp) {
if (!last) last = timestamp;
const dt = Math.min((timestamp - last) / 1000, .04); last = timestamp;
const steps = 3;
for (let i = 0; i < steps; i++) update(dt / steps);
drawBackground(); drawBricks(); drawParticles(); drawPaddle(); drawBall();
requestAnimationFrame(frame);
}
function movePointer(e) {
if (demo || gameOver) return;
const rect = canvas.getBoundingClientRect();
paddle.x = (e.clientX - rect.left) / rect.width * W;
}
field.addEventListener('pointerdown', e => {
startGame(); movePointer(e);
if (e.pointerType !== 'mouse') field.setPointerCapture(e.pointerId);
});
field.addEventListener('pointermove', movePointer);
document.addEventListener('keydown', e => {
if (['ArrowLeft','ArrowRight','ArrowUp','ArrowDown',' '].includes(e.key)) e.preventDefault();
if (demo || gameOver) startGame();
keys.add(e.key);
});
document.addEventListener('keyup', e => keys.delete(e.key));
window.addEventListener('blur', () => keys.clear());
makeBricks();
requestAnimationFrame(frame);
})();
</script>
</body>
</html>Reasoning trace (3,567 tokens)
**Planning card canvas layout** I’m thinking about creating a card canvas with a border and side section. The actual canvas needs to be large, with a viewport height of 800. So, let’s sketch out the page: I’d go with a header that has a max width of 1120, with padding of 24 and a height of 74. On the left, I’d include a logo with a white heart in a rounded salmon square alongside “BURGER BREAKER” and the subline “THE LOVE ARCADE.” On the right, there’d be a label saying “A LITTLE ARCADE LOVE” and “♥ 01 / 03.” To top it off, I’d center a large heading at around y=100 saying “BREAK SOME HEARTS.” Plus, I’ll add a caption. For the main board, it would range from y=171 to y=690.**Designing game layout** I’m working on a game layout with specific dimensions: 800x520 for the board and 228 for the sidebar. The board dimensions might be 840x520, needing all three rows of bricks and a paddle. I’m thinking of an aesthetics-rich design with pastel bricks in five colors, each with tiny glossy highlights and little faces. The goal? To break hearts! I’ll incorporate a header with scores and a cute title that captures the fun theme of the game.**Structuring game interface** I’m designing the game's interface, including a side panel with instructions like "HOW TO PLAY," "01 MOVE," "02 BOUNCE," and "03 SPREAD THE LOVE," and considering a love meter feature. The scoreboard should be dynamic, fitting within the arcade theme. The game board's dimensions seem to need a careful balance; the play area must be efficient without feeling cramped. The main title will be around y=90, and the footer will sit at the bottom. I’m finalizing the canvas size around 900x540 and organizing the layout for smooth gameplay!**Designing a game layout** I'm thinking about a design for a game that includes rows of colorful candy-like blocks. Each block could feature a heart shape and maybe have a waffle-like appearance. I want a visually appealing field with a subtle cream background, and the game field could be dark with neon pastel colors. The user requested lots of hearts, aiming for 35-50 heart particles per block with physics for collisions, increasing the excitement when the ball hits.**Developing game mechanics** I'm considering how the ball should behave in the game. After its first hit, it would take about a second to reach the paddle and a second to bounce back. To make things visually appealing, I could add heart particles that linger for 2 seconds around the bounce area, creating a sparkly effect. I need the ball to start at a specific height and be able to hit multiple targets within a short time frame. Also, player movement should be intuitive, allowing for keyboard and mouse controls. The paddle should resemble a hamburger in design.**Enhancing game features** I'm thinking about adding a cute face to the hamburger paddle, maybe giving it little eyes and a smile. This could add some charm! For the particle effects, I want a big burst of hearts that animate with robust physics and collision detection. The ball should naturally aim for the paddle, and gameplay updates every animation frame. Initially, the AI paddle could move towards the ball, while I set the ball's velocity at 230,-260. I want to ensure particles look glowing and layered effectively.**Evaluating collision mechanics** I'm outlining how to handle collisions in a game. I'll detect if the ball intersects with bricks or the paddle using simple boundary checks. For explosive bricks, I'll ensure they get hit one at a time based on proximity. The paddle is set at y=480, and it'll only detect downward crossings with dynamic bounce angles. The ball starts at x 450, y 250, and I'll need to track its speed and collisions effectively. If the player misses, the game can update lives and offer a restart option.**Investigating user interactions** I’m addressing the interaction between buttons and canvas without an overlay. I'll ensure that mouse and keyboard inputs properly start the demo game—clicks and key presses should initiate it, excluding modifier keys. For styles, I'll use a dark background with scattered stars and blocks. I need clear labels for interactions, and typography will include a stacked system like Trebuchet MS. Final adjustments for layout width are necessary, and I’ll consider decorative elements like accents and the brand icon’s styling.**Structuring the page layout** I'm designing the layout for the page with a maximum width of 1100 pixels. The main title will have a flex display, and I'm considering a sidebar with a dark purple border. For the "THE SPECIAL" card, I could use an inline SVG for a decorative burger icon, since external resources aren’t allowed. The sidebar will be about 216 pixels wide, featuring "TODAY'S SPECIAL" with an illustration and feature text below the controls. Time is limited, so I’ll need to keep things coherent yet visually appealing.**Designing overlay features** I’m thinking about putting an overlay on the interface at 42% to cover the central blank area, labeling it "DEMO MODE" and making it clickable to start a white panel. This might obscure some gameplay in the center though. I could try a small translucent prompt at the top right instead. The overlay could have text that invites clicks to start the demo, and I’ll ensure it doesn’t block important elements like the paddle.**Adding game controls and indicators** I’m considering adding extra card controls labeled "HOW TO PLAY," featuring arrow key buttons and a small cursor icon. There will also be a message saying, "Every brick is full of love," along with a dynamic visual progress indicator that updates with "BRICKS BUSTED" and a count (e.g., "0 / 55"). I need to fit two cards with specific heights: the top at 220, the middle at 205, and the bottom at 120. The board top will also show dynamic scores and control icons.**Planning game visuals** I'm considering the color palette for my game. I think a dark purple playfield with a cream light for the board could work well. Maybe I can use a pink decorative line at the top. For the background, I want a star grid and six rows of bricks, with a focus on high accuracy for collisions. I'll draw backgrounds using gradients, faint grid lines, and include fun elements like ambient hearts and sparkles to enhance the game experience!**Detailing brick and particle design** I'm visualizing each brick as a small heart centered on it, with a semi-translucent white color and a subtle shine in the top-left. I want to establish that bricks are in a 5-row configuration, and I've calculated their positioning. The canvas dimensions will be 900x540, and I'll ensure it's responsive. I'm considering the initial ball velocity and the timing for its interactions with the bricks, with particles visible around three seconds in. Overall, it’s about achieving smooth movement and engaging visuals with hearts and explosion effects!**Aligning burger components** I'm working on rendering the burger's top bun with a drop shadow, positioning it from y=480 to y=498. However, the collision will actually happen at y=480. I need to ensure the shapes align properly, so the paddle is at y=477, the top of the bun is around y=476, and the patty is centered at y+19. I think getting these alignments right will help create a cohesive and visually appealing burger design!**Planning design elements** I'm looking to ensure my code is valid, considering using CSS @media for responsive design. I think I'll incorporate inline SVG for the top logo to add a nice touch with a heart design. On the right side, I want to use inline SVG for the burger art, aiming to manually shape it beautifully with sparkles. It's all about creating an appealing design, so now I just need to start coding!