Hamburger breakoutOne-line
GPT-5 Nano
by OpenAIReasoningClean
Running live in a sandboxed frame. Click inside it before using the keyboard.
How it went
- Total time
- 1 min 23 s
- Cost
- $0.0044
- Output tokens
- 10,949
- Spent thinking
- 6,848 tokens
- Speed
- 136.8 tok/s
- Console errors
- 0
- First token after
- 3.0 s
- First visible text after
- 1 min 2 s
- Prompt tokens
- 357
- Code size
- 12.9 KB
- Finish reason
- stop
- Served by
- OpenAI
- Model id
openai/gpt-5-nano- Reasoning sent
model default- 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 · 482 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Hamburger Breakout: Hearts from Bricks</title>
<style>
:root {
--bg1: #0b1020;
--bg2: #1a1f2e;
--panel: rgba(0,0,0,0.25);
--white: #ffffff;
}
* { box-sizing: border-box; }
html, body {
height: 100%;
margin: 0;
background: linear-gradient(#0b1020, #1a1f2e);
color: #fff;
font-family: system-ui, -apple-system, "Segoe UI", Roboto, Arial;
overflow: hidden; /* satisfy "no horizontal scrollbar" and keep sandbox tidy */
}
.wrapper {
width: 100%;
height: 100%;
display: grid;
grid-template-rows: auto 1fr auto;
align-items: start;
justify-items: center;
padding: 12px;
}
header {
text-align: center;
margin: 6px 0 6px;
user-select: none;
}
h1 {
font-size: clamp(20px, 4vw, 32px);
margin: 0;
letter-spacing: .2px;
text-shadow: 0 2px 6px rgba(0,0,0,.4);
}
p.sub {
margin: 6px 0 0;
font-size: 12px;
color: #ddd;
opacity: .9;
}
.stage {
position: relative;
width: min(94vw, 960px);
aspect-ratio: 16 / 9;
background: radial-gradient(circle at 30% 20%, rgba(255,255,255,.08), rgba(0,0,0,0) 40%), #060913;
border: 1px solid rgba(255,255,255,.08);
border-radius: 14px;
box-shadow: 0 20px 40px rgba(0,0,0,.4);
overflow: hidden;
display: grid;
place-items: center;
}
canvas {
width: 100%;
height: 100%;
display: block;
/* Crisp rendering on high DPI devices */
image-rendering: optimizeQuality;
}
/* Overlay shown before start: "Click or press a key to start" */
.overlay {
position: absolute;
inset: 0;
display: grid;
place-items: center;
background: rgba(0,0,0,.35);
backdrop-filter: blur(1px);
text-align: center;
padding: 20px;
cursor: pointer;
user-select: none;
transition: opacity .2s ease;
}
.overlay h2 {
font-size: clamp(20px, 5vw, 38px);
margin: 0 0 6px;
text-shadow: 0 2px 8px rgba(0,0,0,.6);
}
.overlay p {
margin: 0;
font-size: 14px;
color: #eaeaea;
opacity: .95;
}
footer {
text-align: center;
color: #bbb;
font-size: 12px;
margin-top: 8px;
}
@media (max-width: 600px) {
.overlay h2 { font-size: 22px; }
}
</style>
</head>
<body>
<div class="wrapper">
<header>
<h1>Hamburger Breakout</h1>
<p class="sub">Paddle is a hamburger. Bricks explode into hearts when destroyed.</p>
</header>
<section class="stage" aria-label="Hamburger Breakout stage">
<canvas id="game" width="960" height="540"></canvas>
<div id="overlay" class="overlay" aria-label="Start screen">
<div>
<h2>Click or press a key to start</h2>
<p>AI will play automatically. Watch the hamburger defend the bricks!</p>
</div>
</div>
</section>
<footer>Hint: The paddle is controlled by a small AI for the demo. Try clicking the stage to begin.</footer>
</div>
<script>
(function () {
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
// Logical game resolution (kept constant, scaled to fit screen)
const LOGICAL_W = 960;
const LOGICAL_H = 540;
// DPI scaling
let dpr = Math.max(1, Math.min(window.devicePixelRatio || 1, 2));
function resize() {
// Fit stage nicely within the viewport while keeping 16:9 aspect
const stage = document.querySelector('.stage');
const cssW = Math.min(window.innerWidth * 0.94, 960);
const cssH = Math.round(cssW * (LOGICAL_H / LOGICAL_W));
canvas.style.width = cssW + 'px';
canvas.style.height = cssH + 'px';
canvas.width = Math.floor(cssW * dpr);
canvas.height = Math.floor(cssH * dpr);
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
}
window.addEventListener('resize', resize);
resize();
// Game state
let started = false;
let bricks = [];
const ROWS = 5;
const COLS = 8;
let brickW = 0;
let brickH = 28;
const GAP_X = 12;
const TOP_OFFSET = 60;
// Paddle (hamburger) state
let paddleX = LOGICAL_W / 2;
const PADDLE_W = 150;
const PADDLE_H = 20;
const PADDLE_Y = LOGICAL_H - 40; // center Y of paddle
// Ball
const BALL_R = 8;
let ballX = LOGICAL_W / 2;
let ballY = PADDLE_Y - BALL_R - 2;
let ballVX = 0;
let ballVY = 0;
let lives = 3;
// Hearts particles
let hearts = [];
// Overlay start element
const overlay = document.getElementById('overlay');
function showOverlay(show) {
overlay.style.display = show ? 'grid' : 'none';
}
showOverlay(true);
// Helpers
function clamp(v, a, b) { return Math.max(a, Math.min(b, v)); }
// Round rectangle polyfill for compatibility
if (!CanvasRenderingContext2D.prototype.roundRect) {
CanvasRenderingContext2D.prototype.roundRect = function (x, y, w, h, r) {
if (w < 2 * r) r = w / 2;
if (h < 2 * r) r = Math.min(r, h / 2);
this.beginPath();
this.moveTo(x + r, y);
this.arcTo(x + w, y, x + w, y + h, r);
this.arcTo(x + w, y + h, x, y + h, r);
this.arcTo(x, y + h, x, y, r);
this.arcTo(x, y, x + w, y, r);
this.closePath();
return this;
};
}
// Initialize bricks
function initBricks() {
bricks = [];
brickW = (LOGICAL_W - 80 * 2 - (COLS - 1) * GAP_X) / COLS; // centered with left/right margins
const offsetX = (LOGICAL_W - (COLS * brickW + (COLS - 1) * GAP_X)) / 2;
for (let r = 0; r < ROWS; r++) {
for (let c = 0; c < COLS; c++) {
const x = offsetX + c * (brickW + GAP_X);
const y = TOP_OFFSET + r * (brickH + 12);
bricks.push({
x, y, w: brickW, h: brickH, alive: true,
color: `hsl(${40 + r * 8}, 85%, 60%)`
});
}
}
}
// Draw hamburger paddle
function drawHamburger(ctx, cx, cyTop, w, h) {
ctx.save();
// Bun top
ctx.fillStyle = '#F5C76B';
ctx.roundRect(cx - w/2, cyTop, w, h * 0.4, 8);
ctx.fill();
// Lettuce / bun mid
ctx.fillStyle = '#2EB872';
ctx.fillRect(cx - w/2 + 6, cyTop + h*0.22, w - 12, h*0.12);
// Patty
ctx.fillStyle = '#D17A2A';
ctx.fillRect(cx - w/2 + 6, cyTop + h*0.25, w - 12, h*0.18);
// Bun bottom
ctx.fillStyle = '#F5B96B';
ctx.beginPath();
ctx.roundRect(cx - w/2, cyTop + h*0.33, w, h*0.37, 8);
ctx.fill();
// Sesame seeds
ctx.fillStyle = '#fff8';
for (let i = 0; i < 6; i++) {
const sx = cx - w/2 + 12 + i*(w/5);
const sy = cyTop + h*0.07 + (i%2)*3;
ctx.fillRect(sx, sy, 2, 4);
}
ctx.restore();
}
// Hearts explosion
function spawnHearts(px, py) {
const count = 24;
for (let i = 0; i < count; i++) {
const ang = Math.random() * Math.PI * 2;
const speed = 1.0 + Math.random() * 2.0;
hearts.push({
x: px, y: py,
vx: Math.cos(ang) * speed,
vy: Math.sin(ang) * speed - 1.0,
life: 120 + Math.random() * 60,
scale: 0.8 + Math.random() * 0.9,
color: Math.random() < 0.5 ? '#FF6B6B' : '#FF3D8A'
});
}
}
// Update game state
let lastTs = 0;
function update(dt) {
if (!started) return;
// Move ball
ballX += ballVX;
ballY += ballVY;
// Walls
if (ballX - BALL_R < 0) {
ballX = BALL_R;
ballVX *= -1;
} else if (ballX + BALL_R > LOGICAL_W) {
ballX = LOGICAL_W - BALL_R;
ballVX *= -1;
}
if (ballY - BALL_R < 0) {
ballY = BALL_R;
ballVY *= -1;
}
// Paddle collision
const halfW = PADDLE_W / 2;
if (ballY + BALL_R >= PADDLE_Y - PADDLE_H/2 &&
ballY + BALL_R <= PADDLE_Y + PADDLE_H/2) {
if (ballX >= paddleX - halfW && ballX <= paddleX + halfW) {
ballY = PADDLE_Y - BALL_R;
const delta = ballX - paddleX;
const norm = delta / halfW;
const maxAngle = 1.2; // radians
const angle = norm * maxAngle;
const speed = Math.hypot(ballVX, ballVY);
ballVX = Math.sin(angle) * speed;
ballVY = -Math.abs(Math.cos(angle) * speed);
}
}
// Bricks collision
for (let b of bricks) {
if (!b.alive) continue;
// Circle-rect collision (approx)
const cx = Math.max(b.x, Math.min(ballX, b.x + b.w));
const cy = Math.max(b.y, Math.min(ballY, b.y + b.h));
const dx = ballX - cx;
const dy = ballY - cy;
const dist = Math.hypot(dx, dy);
if (dist < BALL_R) {
// Reflect based on impact side
const overlapX = (ballX + BALL_R) - b.x;
const overlapX2 = (b.x + b.w) - (ballX - BALL_R);
const overlapY = (ballY + BALL_R) - b.y;
const overlapY2 = (b.y + b.h) - (ballY - BALL_R);
const minOverlapX = Math.min(Math.abs(overlapX), Math.abs(overlapX2));
const minOverlapY = Math.min(Math.abs(overlapY), Math.abs(overlapY2));
if (minOverlapX < minOverlapY) ballVX *= -1;
else ballVY *= -1;
b.alive = false;
spawnHearts(b.x + b.w/2, b.y + b.h/2);
break;
}
}
// Hearts update
for (let i = hearts.length - 1; i >= 0; i--) {
const h = hearts[i];
h.x += h.vx;
h.y += h.vy;
h.vy += 0.04;
h.life -= 1;
if (h.life <= 0) hearts.splice(i, 1);
}
// Bottom life loss
if (ballY - BALL_R > LOGICAL_H) {
lives -= 1;
if (lives <= 0) {
// Reset to initial state
started = false;
lives = 3;
initBricks();
}
// Reset ball near paddle
ballX = paddleX;
ballY = PADDLE_Y - BALL_R - 2;
ballVX = (Math.random() * 2 - 1) * 4;
ballVY = -4;
// Pause briefly
// (kept simple for demo)
}
}
// Draw scene
function draw() {
// Clear
ctx.clearRect(0, 0, LOGICAL_W, LOGICAL_H);
// Bricks
for (let b of bricks) {
if (!b.alive) continue;
ctx.fillStyle = b.color;
ctx.fillRect(b.x, b.y, b.w, b.h);
ctx.fillStyle = 'rgba(255,255,255,0.08)';
ctx.fillRect(b.x, b.y, b.w, b.h);
}
// Paddle (hamburger)
drawHamburger(ctx, paddleX, PADDLE_Y - PADDLE_H/2, PADDLE_W, PADDLE_H);
// Ball
ctx.fillStyle = '#222';
ctx.beginPath();
ctx.arc(ballX, ballY, BALL_R, 0, Math.PI * 2);
ctx.fill();
ctx.strokeStyle = '#333';
ctx.stroke();
// Hearts
for (let h of hearts) {
ctx.save();
ctx.globalAlpha = Math.max(0, h.life / 180);
ctx.translate(h.x, h.y);
ctx.scale(h.scale, h.scale);
ctx.fillStyle = h.color;
ctx.beginPath();
// simple heart shape
ctx.moveTo(0, 0);
ctx.arc(-6, -4, 6, Math.PI, 0, false);
ctx.arc(6, -4, 6, Math.PI, 0, false);
ctx.quadraticCurveTo(0, 12, -6, 0);
ctx.fill();
ctx.restore();
}
// HUD
ctx.fillStyle = '#fff';
ctx.font = '14px sans-serif';
ctx.fillText('Lives: ' + lives, 10, 20);
const remaining = bricks.filter(b => b.alive).length;
ctx.fillText('Bricks: ' + remaining, 10, 40);
}
// Main loop
function loop(ts) {
if (!lastTs) lastTs = ts;
const dt = Math.min(0.033, (ts - lastTs) / 1000);
lastTs = ts;
update(dt);
draw();
requestAnimationFrame(loop);
}
// Start game
function startGame() {
if (started) return;
started = true;
ballVX = (Math.random() * 2 - 1) * 3;
ballVY = -4;
showOverlay(false);
}
// Auto-pilot (AI) for paddle movement
function autoPilot() {
if (started) {
const target = ballX;
const speed = 4;
const dx = target - paddleX;
if (Math.abs(dx) > 2) {
paddleX += Math.sign(dx) * speed;
const minX = PADDLE_W / 2;
const maxX = LOGICAL_W - PADDLE_W / 2;
if (paddleX < minX) paddleX = minX;
if (paddleX > maxX) paddleX = maxX;
}
}
requestAnimationFrame(autoPilot);
}
// Init
initBricks();
ballX = paddleX;
ballY = PADDLE_Y - BALL_R - 2;
// Events: start on click or key press
overlay.addEventListener('click', startGame, { passive: true });
window.addEventListener('keydown', function onKey(e) {
if (!started) {
startGame();
}
}, { passive: true });
// Start animation
requestAnimationFrame((t) => {
lastTs = t;
loop(t);
});
autoPilot();
// Kick off resize to set up DPR-scale canvas
})();
</script>
</body>
</html>Reasoning trace (6,848 tokens)
**Building a breakout game demo** I need to create a single HTML file for a self-contained web demo of a Breakout game. In this version, the paddle will be a hamburger, and when bricks get destroyed, they explode into hearts. I want it to be a self-playing demo with a "Click or press a key to start" message until activated. The layout should adapt to sizes from 1280x800 down to 375px. Since no external assets are allowed, I need to use canvas and CSS to draw shapes like the hamburger paddle and hearts.**Creating game mechanics and visuals** I need to avoid using emojis if they could create issues, so I can draw small heart shapes with the canvas using paths or simple colored shapes. I must ensure good performance, especially with my plan to spawn 20-40 hearts per brick—though that might be heavy, it should be manageable. For the self-playing mode, I’ll implement simple AI to make the paddle track the ball. The message "Click or press a key to start" will remain until the user activates the canvas, after which the AI takes over. I'll use HTML canvas for rendering and set up the game loop.**Designing the game elements** I’ll create the "hamburger paddle" as a simplified rounded rectangle shape, resembling a hamburger with buns and filling. For the canvas, I can use arcs and rectangles to draw this. I’ll set up a bricks grid, maintaining properties like position, dimensions, color, and existence. When bricks are destroyed, I’ll spawn heart-shaped particles using an array to track their position and movement. I’ll define a function to draw these hearts, which will have gravity and fade out. The paddle will measure around 150 px in width and will sit at the bottom of the canvas near the designated paddleY position.**Implementing game dynamics** I’m going to treat the paddle as fixed on the y-axis, letting the AI control its x-position. For collision detection, if the ball intersects with a brick, I’ll invert its vertical velocity, mark the brick as destroyed, and spawn hearts with some velocity from the brick’s position. If the ball falls past the bottom, I’ll reset it and let the AI continue. To keep things simple for the demo, I might just reset the ball without a delay. I’ll add a "Click or press a key to start" message overlay until the game begins, using a semi-transparent dark layer for that. For mobile, I’ll consider touch input as well.**Setting up the game page** I need to ensure the page adapts to various screen sizes, implementing key and click events only after the "started" state is true. The canvas will be designed responsively, fitting within a 1280x800 viewport and scaling down to 375px wide without horizontal scrollbars. I'll use CSS to establish a background and set the canvas width to fit while maintaining the aspect ratio. The gameplay elements will include an 8x5 grid of bricks, the ball, and the hamburger paddle, with collision detection to handle interactions. Hearts will spawn on brick destruction, and AI will control paddle movement toward the ball. I need to approach window resizing effectively to adjust the canvas accordingly.**Implementing game controls and setup** I want to ensure that the AI continues smoothly, conserving lives and managing frames. When reset, the ball should start near the paddle but with an initial downward velocity for a bit of challenge. The keydown events will only register after the user has clicked on the iframe—this is crucial to follow the instructions for starting the game. I will set up a responsive HTML structure with a canvas, ensuring everything scales properly. The code will establish the game's logic, like drawing a hamburger-shaped paddle and managing bricks and heart particle effects while maintaining performance.**Adding compatibility and game mechanics** I need to implement a polyfill for the canvas's `roundRect` method if it's not already available. This will allow better compatibility across different browsers. I’m also working on a function to spawn hearts as particles when bricks are hit. Each heart will have random speeds and lifetimes, adding a nice visual effect. The game update loop manages ball movement, collisions with walls, paddles, and bricks, as well as updating heart positions and handling game resets when lives are lost. It’s a lot, but it’s crucial for smooth gameplay!**Implementing game corrections** I'm setting up an auto-pilot feature to move the paddle toward the ball during gameplay. It's important to keep the paddle within boundaries, so I'll ensure to clamp its position. I also need to create an overlay message prompting users to start the game. This involves adding translucent rectangles and center-aligned text. Additionally, I’m refining the hearts' appearance and making sure the code runs error-free, adjusting calculations for brick positioning and ensuring the paddle and hamburger drawing functions are correctly aligned. Overall, it’s about organizing the logic and visuals!**Creating the overlay functionality** I'm looking at how the hearts function creates a heart shape using arcs and curves, but it's not perfect. I still need to implement the starting overlay that should be visible from the first paint. This overlay will require proper HTML and CSS positioning to be on top of the canvas. I’ll make the overlay clickable to start the game, ensuring that the keyboard events will only be captured once the game has started. I'll toggle a boolean for the game state and focus on making everything function seamlessly. Now, let’s finalize that HTML code!