Hamburger breakoutOne-line
Claude Haiku 4.5
by AnthropicReasoningClean
Running live in a sandboxed frame. Click inside it before using the keyboard.
How it went
- Total time
- 26.7 s
- Cost
- $0.047
- Output tokens
- 9,297
- Spent thinking
- 5,148 tokens
- Speed
- 360.7 tok/s
- Console errors
- 0
- First token after
- 903 ms
- First visible text after
- 23.9 s
- Prompt tokens
- 408
- Code size
- 13.4 KB
- Finish reason
- stop
- Served by
- Amazon Bedrock
- Model id
anthropic/claude-haiku-4.5- Reasoning sent
{"enabled":true}- 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 · 388 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hamburger Breakout</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
font-family: Arial, sans-serif;
overflow: hidden;
}
#gameContainer {
position: relative;
width: min(90vw, 800px);
height: min(90vh, 600px);
background: white;
border-radius: 10px;
box-shadow: 0 10px 40px rgba(0,0,0,0.3);
overflow: hidden;
}
canvas {
display: block;
width: 100%;
height: 100%;
}
#startMessage {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0,0,0,0.8);
color: white;
padding: 30px;
border-radius: 10px;
text-align: center;
z-index: 10;
pointer-events: none;
font-size: clamp(14px, 4vw, 24px);
}
#startMessage.hidden {
display: none;
}
</style>
</head>
<body>
<div id="gameContainer">
<canvas id="gameCanvas"></canvas>
<div id="startMessage">🎮 Click or press any key to start!</div>
</div>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const startMessage = document.getElementById('startMessage');
function resizeCanvas() {
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
}
resizeCanvas();
window.addEventListener('resize', resizeCanvas);
let gameState = 'demo';
let isAutoPlay = true;
const paddle = {
x: 0,
y: 0,
width: 60,
height: 40,
speed: 5
};
const ball = {
x: 0,
y: 0,
radius: 6,
vx: 4,
vy: -4
};
let bricks = [];
let particles = [];
let score = 0;
function initBricks() {
bricks = [];
const brickWidth = canvas.width / 8;
const brickHeight = 20;
const padding = 5;
for (let col = 0; col < 8; col++) {
for (let row = 0; row < 4; row++) {
bricks.push({
x: col * brickWidth + padding,
y: 30 + row * (brickHeight + padding),
width: brickWidth - padding * 2,
height: brickHeight,
active: true
});
}
}
}
function init() {
paddle.x = (canvas.width - paddle.width) / 2;
paddle.y = canvas.height - 50;
ball.x = paddle.x + paddle.width / 2;
ball.y = paddle.y - 20;
score = 0;
particles = [];
initBricks();
}
init();
function createHeartExplosion(x, y) {
const heartCount = Math.floor(Math.random() * 15 + 20);
for (let i = 0; i < heartCount; i++) {
const angle = (Math.PI * 2 * i) / heartCount + (Math.random() - 0.5) * 0.8;
const velocity = Math.random() * 2.5 + 2;
particles.push({
x: x,
y: y,
vx: Math.cos(angle) * velocity,
vy: Math.sin(angle) * velocity,
life: 1,
size: Math.random() * 10 + 6
});
}
}
function drawHamburger(x, y, width, height) {
const bunColor = '#D2691E';
const meatColor = '#8B4513';
const lettuceColor = '#228B22';
const cheeseColor = '#FFD700';
ctx.fillStyle = bunColor;
ctx.beginPath();
ctx.ellipse(x + width/2, y + height * 0.15, width/2, height * 0.15, 0, 0, Math.PI * 2);
ctx.fill();
ctx.strokeStyle = '#A0522D';
ctx.lineWidth = 1;
ctx.stroke();
ctx.fillStyle = '#F5DEB3';
for (let i = 0; i < 5; i++) {
ctx.beginPath();
ctx.arc(x + (i + 1) * (width / 6), y + height * 0.1, 2, 0, Math.PI * 2);
ctx.fill();
}
ctx.fillStyle = lettuceColor;
ctx.fillRect(x + 2, y + height * 0.22, width - 4, height * 0.12);
ctx.fillStyle = cheeseColor;
ctx.fillRect(x + 2, y + height * 0.35, width - 4, height * 0.1);
ctx.fillStyle = meatColor;
ctx.fillRect(x + 2, y + height * 0.48, width - 4, height * 0.1);
ctx.fillRect(x + 2, y + height * 0.62, width - 4, height * 0.1);
ctx.fillStyle = bunColor;
ctx.beginPath();
ctx.ellipse(x + width/2, y + height - height * 0.15, width/2, height * 0.15, 0, 0, Math.PI * 2);
ctx.fill();
ctx.strokeStyle = '#A0522D';
ctx.lineWidth = 1;
ctx.stroke();
}
function drawHeart(x, y, size) {
ctx.fillStyle = '#FF1493';
ctx.beginPath();
const s = size;
ctx.moveTo(x, y - s * 0.35);
ctx.bezierCurveTo(x - s * 0.5, y - s * 0.8, x - s * 0.8, y - s * 0.5, x - s * 0.8, y - s * 0.1);
ctx.bezierCurveTo(x - s * 0.8, y + s * 0.3, x - s * 0.3, y + s * 0.7, x, y + s);
ctx.bezierCurveTo(x + s * 0.3, y + s * 0.7, x + s * 0.8, y + s * 0.3, x + s * 0.8, y - s * 0.1);
ctx.bezierCurveTo(x + s * 0.8, y - s * 0.5, x + s * 0.5, y - s * 0.8, x, y - s * 0.35);
ctx.fill();
}
function update() {
if (gameState !== 'playing' && gameState !== 'demo') return;
if (isAutoPlay) {
const targetX = ball.x - paddle.width / 2;
if (Math.abs(paddle.x - targetX) > paddle.speed) {
paddle.x += Math.sign(targetX - paddle.x) * paddle.speed;
}
}
ball.x += ball.vx;
ball.y += ball.vy;
if (ball.x - ball.radius < 0 || ball.x + ball.radius > canvas.width) {
ball.vx = -ball.vx;
ball.x = Math.max(ball.radius, Math.min(canvas.width - ball.radius, ball.x));
}
if (ball.y - ball.radius < 0) {
ball.vy = -ball.vy;
ball.y = ball.radius;
}
if (ball.y > canvas.height) {
gameState = 'gameOver';
}
if (ball.y + ball.radius > paddle.y &&
ball.y - ball.radius < paddle.y + paddle.height &&
ball.x > paddle.x &&
ball.x < paddle.x + paddle.width) {
ball.vy = -Math.abs(ball.vy);
const hitPos = (ball.x - paddle.x) / paddle.width;
ball.vx = (hitPos - 0.5) * 8;
ball.y = paddle.y - ball.radius;
}
for (let brick of bricks) {
if (!brick.active) continue;
if (ball.x + ball.radius > brick.x &&
ball.x - ball.radius < brick.x + brick.width &&
ball.y + ball.radius > brick.y &&
ball.y - ball.radius < brick.y + brick.height) {
brick.active = false;
createHeartExplosion(brick.x + brick.width / 2, brick.y + brick.height / 2);
score += 10;
const overlapLeft = ball.x + ball.radius - brick.x;
const overlapRight = brick.x + brick.width - (ball.x - ball.radius);
const overlapTop = ball.y + ball.radius - brick.y;
const overlapBottom = brick.y + brick.height - (ball.y - ball.radius);
const minOverlap = Math.min(overlapLeft, overlapRight, overlapTop, overlapBottom);
if (minOverlap === overlapLeft || minOverlap === overlapRight) {
ball.vx = -ball.vx;
} else {
ball.vy = -ball.vy;
}
}
}
if (bricks.every(b => !b.active)) {
gameState = 'won';
}
for (let i = particles.length - 1; i >= 0; i--) {
const p = particles[i];
p.x += p.vx;
p.y += p.vy;
p.vy += 0.15;
p.life -= 0.025;
if (p.life <= 0) {
particles.splice(i, 1);
}
}
}
function draw() {
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = '#333';
ctx.font = 'bold ' + Math.floor(canvas.height * 0.04) + 'px Arial';
ctx.fillText('Score: ' + score, 10, 25);
ctx.fillStyle = '#FF6B6B';
for (let brick of bricks) {
if (brick.active) {
ctx.fillRect(brick.x, brick.y, brick.width, brick.height);
ctx.strokeStyle = '#CC5555';
ctx.lineWidth = 1;
ctx.strokeRect(brick.x, brick.y, brick.width, brick.height);
}
}
ctx.fillStyle = '#333';
ctx.beginPath();
ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);
ctx.fill();
drawHamburger(paddle.x, paddle.y, paddle.width, paddle.height);
for (let p of particles) {
ctx.globalAlpha = p.life;
drawHeart(p.x, p.y, p.size);
ctx.globalAlpha = 1;
}
if (gameState === 'gameOver') {
ctx.fillStyle = 'rgba(0,0,0,0.5)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'white';
ctx.font = 'bold ' + Math.floor(canvas.height * 0.08) + 'px Arial';
ctx.textAlign = 'center';
ctx.fillText('Game Over!', canvas.width / 2, canvas.height / 2);
ctx.textAlign = 'left';
}
if (gameState === 'won') {
ctx.fillStyle = 'rgba(0,0,0,0.5)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'white';
ctx.font = 'bold ' + Math.floor(canvas.height * 0.08) + 'px Arial';
ctx.textAlign = 'center';
ctx.fillText('You Won! 🎉', canvas.width / 2, canvas.height / 2);
ctx.textAlign = 'left';
}
}
function gameLoop() {
update();
draw();
requestAnimationFrame(gameLoop);
}
gameLoop();
document.addEventListener('mousemove', (e) => {
if (gameState !== 'playing') return;
const rect = canvas.getBoundingClientRect();
const mouseX = e.clientX - rect.left;
paddle.x = mouseX - paddle.width / 2;
paddle.x = Math.max(0, Math.min(canvas.width - paddle.width, paddle.x));
isAutoPlay = false;
});
document.addEventListener('touchmove', (e) => {
if (gameState !== 'playing') return;
e.preventDefault();
const rect = canvas.getBoundingClientRect();
const touchX = e.touches[0].clientX - rect.left;
paddle.x = touchX - paddle.width / 2;
paddle.x = Math.max(0, Math.min(canvas.width - paddle.width, paddle.x));
isAutoPlay = false;
});
document.addEventListener('click', () => {
if (gameState === 'demo') {
gameState = 'playing';
isAutoPlay = false;
startMessage.classList.add('hidden');
} else if (gameState === 'gameOver' || gameState === 'won') {
init();
gameState = 'playing';
isAutoPlay = false;
startMessage.classList.add('hidden');
}
});
document.addEventListener('keydown', (e) => {
if (gameState === 'demo') {
gameState = 'playing';
isAutoPlay = false;
startMessage.classList.add('hidden');
} else if (gameState === 'gameOver' || gameState === 'won') {
init();
gameState = 'playing';
isAutoPlay = false;
startMessage.classList.add('hidden');
}
});
</script>
</body>
</html>Reasoning trace (5,148 tokens)
The user wants a breakout game with:
1. A paddle that looks like a hamburger
2. Bricks that explode into hearts when broken
This is a game, so it needs to:
- Start in a self-playing demo mode with "Click or press a key to start" message
- Have all assets generated inline (no external images)
- Be self-contained HTML with inline CSS and JavaScript
- Work in 1280×800 viewport and adapt to 375px
- Have meaningful visuals immediately visible
I'll create:
1. A canvas-based breakout game
2. SVG/CSS hamburger paddle
3. Exploding hearts particle effect when bricks break
4. AI demo mode for auto-playing
5. Click/key to start real play
Let me build this:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hamburger Breakout</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
font-family: Arial, sans-serif;
overflow: hidden;
}
#gameContainer {
position: relative;
width: min(90vw, 800px);
height: min(90vh, 600px);
background: white;
border-radius: 10px;
box-shadow: 0 10px 40px rgba(0,0,0,0.3);
overflow: hidden;
}
canvas {
display: block;
width: 100%;
height: 100%;
}
#startMessage {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0,0,0,0.8);
color: white;
padding: 30px;
border-radius: 10px;
text-align: center;
z-index: 10;
pointer-events: none;
font-size: clamp(14px, 2vw, 18px);
```
I'm setting up the container with a gradient background, rounded corners, and a centered overlay for the start message that'll sit above the canvas.
Next I'll build the JavaScript game logic—setting up the canvas context, handling resize, and defining the core states (demo autoplay, playing, gameOver, won) along with the paddle object properties.
I'm defining the ball with position, radius, velocity, and speed, then setting up arrays for bricks and particles plus a score tracker. The initBricks function lays out an 8-column, 4-row grid with padding calculations based on canvas width.
Next I'm centering the paddle and positioning the ball above it in an init function, resetting score and particles, then calling init() to start. For visual flair, I'm building a heart-explosion particle system—createHeartExplosion spawns 15-30 particles radiating outward in a circle with randomized angle, velocity, and size, each tracking life/maxLife for fading.
Now I'm drawing the hamburger paddle piece by piece. I'm defining colors for bun, meat, lettuce, cheese, then drawing an ellipse for the top bun with a brown stroke outline. I'm scattering sesame seed dots across the top, and starting to layer lettuce beneath it.
// Draw heart shape
ctx.moveTo(x, y - s * 0.35);
ctx.bezierCurveTo(x - s * 0.5, y - s * 0.8, x - s * 0.8, y - s * 0.5, x - s * 0.8, y - s * 0.1);
ctx.bezierCurveTo(x - s * 0.8, y + s * 0.3, x - s * 0.3, y + s * 0.7, x, y + s);
ctx.bezierCurveTo(x + s * 0.3, y + s * 0.7, x + s * 0.8, y + s * 0.3, x + s * 0.8, y - s * 0.1);
ctx.bezierCurveTo(x + s * 0.8, y - s * 0.5, x + s * 0.5, y - s * 0.8, x, y - s * 0.35);
ctx.fill();
}
For the update loop, I need demo mode AI that tracks the ball with the paddle, moving toward targetX based on ball position minus half paddle width, clamped by paddle speed.
Then ball movement: add velocity, bounce off side and top walls, lose if it falls past canvas height, bounce off paddle with angle based on hit position, and check brick collisions using overlap detection to pick bounce axis, spawning heart explosions and adding score on hits. Particles get gravity and fade out over time, removed when life hits zero.
Drawing covers score text, active bricks with outlines, the ball, the hamburger paddle, fading heart particles, and overlay messages for game over or win states showing final score.
The game loop calls update and draw repeatedly via requestAnimationFrame. Input handling covers mouse and touch movement for the paddle, plus click/keydown to transition from demo to playing or restart after game over/win, and arrow keys for manual paddle control, all disabling auto-play once used.
This covers the demo mode, hamburger paddle, heart explosions, start message, self-contained responsive layout, and no external dependencies. The hamburger and hearts should render clearly, and the start message visibility toggles correctly based on game state. The implementation looks complete.