Hamburger breakoutOne-line
Gemini 3.8 Flash
by GoogleReasoningClean
Running live in a sandboxed frame. Click inside it before using the keyboard.
How it went
- Total time
- 35.7 s
- Cost
- $0.025
- Output tokens
- 6,637
- Spent thinking
- 0 tokens
- Speed
- 192.2 tok/s
- Console errors
- 0
- First token after
- 1.2 s
- First visible text after
- 1.2 s
- Prompt tokens
- 363
- Code size
- 15.8 KB
- Finish reason
- stop
- Served by
- Model id
google/gemini-3.8-flash- Reasoning sent
{"effort":"low"}- Max output
- 65,536 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 · 655 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Burger Breakout - Heart Explosion Edition</title>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
user-select: none;
}
body {
background: radial-gradient(circle at center, #2b1025 0%, #110515 100%);
color: #fff;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
overflow: hidden;
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
#game-wrapper {
position: relative;
width: 100%;
max-width: 900px;
height: 100%;
max-height: 700px;
display: flex;
flex-direction: column;
box-shadow: 0 0 50px rgba(255, 64, 129, 0.25);
border-radius: 16px;
border: 2px solid rgba(255, 128, 171, 0.3);
background: #1a081f;
}
#ui-bar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 24px;
background: rgba(40, 10, 45, 0.8);
border-bottom: 2px solid rgba(255, 128, 171, 0.2);
font-weight: bold;
font-size: 1.1rem;
text-transform: uppercase;
letter-spacing: 1px;
z-index: 10;
}
.stat {
display: flex;
align-items: center;
gap: 8px;
text-shadow: 0 0 10px rgba(255, 105, 180, 0.8);
}
.stat span {
color: #ff80ab;
font-size: 1.3rem;
}
canvas {
flex: 1;
width: 100%;
height: 100%;
display: block;
cursor: none;
}
#overlay {
position: absolute;
top: 50px;
left: 0;
right: 0;
bottom: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-end;
padding-bottom: 80px;
pointer-events: none;
transition: opacity 0.3s;
}
.banner {
background: rgba(25, 5, 30, 0.85);
border: 2px solid #ff4081;
box-shadow: 0 0 25px #ff4081;
padding: 12px 28px;
border-radius: 50px;
text-align: center;
animation: pulse 1.5s infinite alternate;
}
.banner h1 {
font-size: 1.3rem;
color: #fff;
margin-bottom: 4px;
letter-spacing: 2px;
text-shadow: 0 0 8px #ff4081;
}
.banner p {
font-size: 0.85rem;
color: #ff80ab;
}
@keyframes pulse {
0% { transform: scale(1); box-shadow: 0 0 15px rgba(255, 64, 129, 0.5); }
100% { transform: scale(1.05); box-shadow: 0 0 30px rgba(255, 64, 129, 0.9); }
}
</style>
</head>
<body>
<div id="game-wrapper">
<div id="ui-bar">
<div class="stat">Score: <span id="score-val">0</span></div>
<div class="stat"><span id="mode-val" style="color:#ffd54f;">🤖 AUTO-DEMO</span></div>
<div class="stat">Hearts Unleashed: <span id="heart-val">0</span></div>
</div>
<canvas id="gameCanvas"></canvas>
<div id="overlay">
<div class="banner">
<h1 id="banner-title">PRESS ANY KEY OR CLICK TO PLAY</h1>
<p id="banner-sub">Control juicy burger with Mouse or Arrow Keys</p>
</div>
</div>
</div>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const scoreEl = document.getElementById('score-val');
const heartEl = document.getElementById('heart-val');
const modeEl = document.getElementById('mode-val');
const overlay = document.getElementById('overlay');
let W, H;
function resize() {
const rect = canvas.getBoundingClientRect();
canvas.width = rect.width;
canvas.height = rect.height;
W = canvas.width;
H = canvas.height;
}
window.addEventListener('resize', resize);
let isAutoPlay = true;
let score = 0;
let totalHeartsExploded = 0;
// Paddle (Juicy Hamburger)
const paddle = {
w: 120,
h: 36,
x: 0,
y: 0,
targetX: 0,
vx: 0
};
// Ball (Tasty Sesame Seed / Pickled Olive / Golden Tomato Seed)
const ball = {
x: 0,
y: 0,
r: 9,
vx: 0,
vy: 0,
speed: 7,
trail: []
};
// Bricks
let bricks = [];
const BRICK_ROWS = 5;
const BRICK_COLS = 9;
const BRICK_COLORS = [
['#ff1744', '#f50057'], // Cherry red
['#ff4081', '#f50057'], // Vibrant pink
['#ff9100', '#ff3d00'], // Bright orange
['#ffd600', '#ffab00'], // Golden yellow
['#00e676', '#00c853'] // Lime crisp
];
// Hearts
let hearts = [];
function initGame() {
resize();
paddle.w = Math.max(90, Math.min(140, W * 0.16));
paddle.h = 32;
paddle.x = W / 2 - paddle.w / 2;
paddle.y = H - 55;
paddle.targetX = paddle.x;
resetBall();
createBricks();
}
function resetBall() {
ball.x = paddle.x + paddle.w / 2;
ball.y = paddle.y - 15;
const angle = -Math.PI / 2 + (Math.random() * 0.6 - 0.3);
ball.speed = Math.max(6.5, W * 0.008);
ball.vx = ball.speed * Math.sin(angle);
ball.vy = -ball.speed * Math.cos(angle);
ball.trail = [];
}
function createBricks() {
bricks = [];
const padding = 8;
const marginTop = 35;
const totalPaddingX = padding * (BRICK_COLS + 1);
const brickW = (W - totalPaddingX) / BRICK_COLS;
const brickH = 22;
for (let r = 0; r < BRICK_ROWS; r++) {
for (let c = 0; c < BRICK_COLS; c++) {
const bx = padding + c * (brickW + padding);
const by = marginTop + r * (brickH + padding);
bricks.push({
x: bx,
y: by,
w: brickW,
h: brickH,
active: true,
color: BRICK_COLORS[r % BRICK_COLORS.length],
scale: 1
});
}
}
}
// Explode into Hearts
function explodeHearts(x, y, w, h, baseColor) {
const count = 55; // Tons of little hearts!
totalHeartsExploded += count;
heartEl.innerText = totalHeartsExploded;
const heartPalettes = [
'#ff1744', '#ff4081', '#f50057', '#ff80ab', '#ff4081',
'#ff6e40', '#ea80fc', '#ffffff', '#ff1493'
];
for (let i = 0; i < count; i++) {
const angle = Math.random() * Math.PI * 2;
const force = Math.random() * 8 + 2;
hearts.push({
x: x + w / 2 + (Math.random() - 0.5) * (w * 0.6),
y: y + h / 2 + (Math.random() - 0.5) * (h * 0.6),
vx: Math.cos(angle) * force,
vy: Math.sin(angle) * force - (Math.random() * 2 + 1), // upward boost
size: Math.random() * 9 + 5,
rot: Math.random() * Math.PI * 2,
vrot: (Math.random() - 0.5) * 0.25,
color: heartPalettes[Math.floor(Math.random() * heartPalettes.length)],
alpha: 1,
decay: Math.random() * 0.012 + 0.008,
gravity: 0.16
});
}
}
// Draw a smooth procedural Heart
function drawHeart(ctx, x, y, size, color, alpha, rot) {
ctx.save();
ctx.translate(x, y);
ctx.rotate(rot);
ctx.globalAlpha = Math.max(0, alpha);
ctx.fillStyle = color;
ctx.shadowColor = color;
ctx.shadowBlur = 8;
ctx.beginPath();
const topCurveHeight = size * 0.3;
ctx.moveTo(0, topCurveHeight);
// Top left curve
ctx.bezierCurveTo(
-size / 2, -topCurveHeight,
-size, size / 3,
0, size
);
// Top right curve
ctx.bezierCurveTo(
size, size / 3,
size / 2, -topCurveHeight,
0, topCurveHeight
);
ctx.closePath();
ctx.fill();
ctx.restore();
}
// Draw the Hamburger Paddle
function drawHamburger(ctx, x, y, w, h) {
ctx.save();
// Floating juice / glow under burger
ctx.shadowColor = '#ff3d00';
ctx.shadowBlur = 12;
const r = 8;
const topBunH = h * 0.36;
const lettuceH = h * 0.14;
const pattyH = h * 0.24;
const cheeseH = h * 0.1;
const botBunH = h * 0.24;
let curY = y;
// 1. TOP BUN (Rounded Golden-Toasted)
ctx.fillStyle = '#e67e22';
ctx.beginPath();
ctx.moveTo(x + 4, curY + topBunH);
ctx.bezierCurveTo(x + 2, curY, x + w - 2, curY, x + w - 4, curY + topBunH);
ctx.closePath();
ctx.fill();
// Bun Highlight
ctx.fillStyle = '#f39c12';
ctx.beginPath();
ctx.ellipse(x + w * 0.5, curY + topBunH * 0.4, w * 0.38, topBunH * 0.25, 0, 0, Math.PI * 2);
ctx.fill();
// Sesame Seeds on top
ctx.fillStyle = '#fff9e6';
ctx.shadowBlur = 0;
const seeds = [0.25, 0.4, 0.55, 0.7, 0.32, 0.48, 0.63];
seeds.forEach((sx, idx) => {
const sy = curY + topBunH * (idx > 3 ? 0.65 : 0.35);
ctx.beginPath();
ctx.ellipse(x + w * sx, sy, 2.2, 1.2, 0.3, 0, Math.PI * 2);
ctx.fill();
});
curY += topBunH;
// 2. CRISP WAVED LETTUCE
ctx.fillStyle = '#2ecc71';
ctx.beginPath();
const waves = 8;
ctx.moveTo(x, curY);
for (let i = 0; i <= waves; i++) {
const wx = x + (w / waves) * i;
const wy = curY + (i % 2 === 0 ? lettuceH : -2);
ctx.lineTo(wx, wy);
}
ctx.lineTo(x + w, curY + lettuceH * 0.6);
ctx.lineTo(x, curY + lettuceH * 0.6);
ctx.closePath();
ctx.fill();
curY += lettuceH * 0.6;
// 3. MELTY AMERICAN CHEESE (Pointed corners hanging down)
ctx.fillStyle = '#f1c40f';
ctx.beginPath();
ctx.moveTo(x + 6, curY);
ctx.lineTo(x + w - 6, curY);
ctx.lineTo(x + w - 2, curY + cheeseH);
ctx.lineTo(x + w * 0.75, curY + cheeseH * 2.2);
ctx.lineTo(x + w * 0.5, curY + cheeseH);
ctx.lineTo(x + w * 0.25, curY + cheeseH * 2.5);
ctx.lineTo(x + 2, curY + cheeseH);
ctx.closePath();
ctx.fill();
curY += cheeseH * 0.7;
// 4. GRILLED BEEF PATTY
ctx.fillStyle = '#5c2c16';
ctx.beginPath();
ctx.roundRect(x + 3, curY, w - 6, pattyH, 5);
ctx.fill();
// Grill marks
ctx.strokeStyle = '#3d1a0a';
ctx.lineWidth = 2.5;
for (let g = 0.2; g < 0.9; g += 0.2) {
ctx.beginPath();
ctx.moveTo(x + w * g, curY + 2);
ctx.lineTo(x + w * g + 8, curY + pattyH - 2);
ctx.stroke();
}
curY += pattyH;
// 5. BOTTOM BUN
ctx.fillStyle = '#d35400';
ctx.beginPath();
ctx.roundRect(x + 6, curY, w - 12, botBunH, [2, 2, 7, 7]);
ctx.fill();
ctx.restore();
}
function update() {
// Demo AI or Human Paddle Movement
if (isAutoPlay) {
// Predictive AI with human-like smoothing
const target = ball.x - paddle.w / 2;
paddle.x += (target - paddle.x) * 0.14;
} else {
paddle.x += (paddle.targetX - paddle.x) * 0.25;
}
// Keep paddle on screen
paddle.x = Math.max(5, Math.min(W - paddle.w - 5, paddle.x));
// Ball Movement
ball.x += ball.vx;
ball.y += ball.vy;
// Trail
ball.trail.push({ x: ball.x, y: ball.y });
if (ball.trail.length > 8) ball.trail.shift();
// Walls
if (ball.x - ball.r < 0) {
ball.x = ball.r;
ball.vx = Math.abs(ball.vx);
} else if (ball.x + ball.r > W) {
ball.x = W - ball.r;
ball.vx = -Math.abs(ball.vx);
}
if (ball.y - ball.r < 0) {
ball.y = ball.r;
ball.vy = Math.abs(ball.vy);
} else if (ball.y + ball.r > H) {
// Missed bottom
if (isAutoPlay) {
resetBall();
} else {
score = Math.max(0, score - 50);
scoreEl.innerText = score;
resetBall();
}
}
// Paddle Collision
if (
ball.y + ball.r >= paddle.y &&
ball.y - ball.r <= paddle.y + paddle.h &&
ball.x >= paddle.x - ball.r &&
ball.x <= paddle.x + paddle.w + ball.r &&
ball.vy > 0
) {
ball.y = paddle.y - ball.r;
// Angle according to hit offset
const hitPoint = (ball.x - (paddle.x + paddle.w / 2)) / (paddle.w / 2);
const maxAngle = Math.PI * 0.42; // Up to ~75 degrees
const angle = hitPoint * maxAngle;
const currentSpeed = Math.min(13, ball.speed * 1.02);
ball.speed = currentSpeed;
ball.vx = currentSpeed * Math.sin(angle);
ball.vy = -currentSpeed * Math.cos(angle);
// Mini burger bounce squish particle effect (cute hearts)
for(let i=0; i<4; i++) {
hearts.push({
x: ball.x,
y: ball.y,
vx: (Math.random() - 0.5) * 5,
vy: -Math.random() * 3 - 1,
size: Math.random() * 5 + 3,
rot: 0,
vrot: 0.1,
color: '#ffea00',
alpha: 0.8,
decay: 0.04,
gravity: 0.1
});
}
}
// Brick Collision
let activeBricksCount = 0;
for (let b of bricks) {
if (!b.active) continue;
activeBricksCount++;
// Nearest point check
const nearestX = Math.max(b.x, Math.min(ball.x, b.x + b.w));
const nearestY = Math.max(b.y, Math.min(ball.y, b.y + b.h));
const distX = ball.x - nearestX;
const distY = ball.y - nearestY;
if ((distX * distX + distY * distY) < (ball.r * ball.r)) {
b.active = false;
score += 100;
scoreEl.innerText = score;
// Burst into tons of adorable little hearts!
explodeHearts(b.x, b.y, b.w, b.h, b.color[0]);
// Bounce direction
const prevX = ball.x - ball.vx;
const prevY = ball.y - ball.vy;
if (prevX < b.x || prevX > b.x + b.w) {
ball.vx = -ball.vx;
} else {
ball.vy = -ball.vy;
}
break;
}
}
// Level Clear -> Rebuild
if (activeBricksCount === 0) {
createBricks();
resetBall();
}
// Update Hearts
for (let i = hearts.length - 1; i >= 0; i--) {
const h = hearts[i];
h.x += h.vx;
h.y += h.vy;
h.vy += h.gravity;
h.vx *= 0.98;
h.rot += h.vrot;
h.alpha -= h.decay;
if (h.alpha <= 0 || h.y > H + 50) {
hearts.splice(i, 1);
}
}
}
function render() {
ctx.clearRect(0, 0, W, H);
// Subtle background star/heart grid
ctx.fillStyle = 'rgba(255, 64, 129, 0.03)';
for (let gx = 20; gx < W; gx += 40) {
for (let gy = 20; gy < H; gy += 40) {
ctx.fillRect(gx, gy, 2, 2);
}
}
// Draw Bricks
for (let b of bricks) {
if (!b.active) continue;
ctx.save();
// Brick Body
const grad = ctx.createLinearGradient(b.x, b.y, b.x, b.y + b.h);
grad.addColorStop(0, b.color[0]);
grad.addColorStop(1, b.color[1]);
ctx.fillStyle = grad;
ctx.shadowColor = b.color[0];
ctx.shadowBlur = 10;
ctx.beginPath();
ctx.roundRect(b.x, b.y, b.w, b.h, 6);
ctx.fill();
// Brick gloss highlight
ctx.fillStyle = 'rgba(255, 255, 255, 0.25)';
ctx.beginPath();
ctx.roundRect(b.x + 2, b.y + 2, b.w - 4, b.h * 0.35, [4, 4, 1, 1]);
ctx.fill();
// Tiny heart embossed in center
drawHeart(ctx, b.x + b.w / 2, b.y + b.h / 2 - 2, 6, 'rgba(255,255,255,0.4)', 0.8, 0);
ctx.restore();
}
// Draw Exploding Hearts (Rendered in background and foreground for depth)
for (let h of hearts) {
drawHeart(ctx, h.x, h.y, h.size, h.color, h.alpha, h.rot);
}
// Draw Ball Trail
for (let i = 0; i < ball.trail.length; i++) {
const t = ball.trail[i];
const tr = ball.r * (i / ball.trail.length);
ctx.beginPath();
ctx.arc(t.x, t.y, tr, 0, Math.PI * 2);
ctx.fillStyle = `rgba(255, 64, 129, ${ (i / ball.trail.length) * 0.4 })`;
ctx.fill();
}
// Draw Ball (Glowing Sweet Heart Berry / Glowing Golden Sphere)
ctx.save();
ctx.shadowColor = '#ff4081';
ctx.shadowBlur = 18;
const bGrad = ctx.createRadialGradient(ball.x - 2, ball.y - 2, 1, ball.x, ball.y, ball.r);
bGrad.addColorStop(0, '#ffffff');
bGrad.addColorStop(0.4, '#ff4081');
bGrad.addColorStop(1, '#c51162');
ctx.fillStyle = bGrad;
ctx.beginPath();
ctx.arc(ball.x, ball.y, ball.r, 0, Math.PI * 2);
ctx.fill();
ctx.restore();
// Draw Hamburger Paddle
drawHamburger(ctx, paddle.x, paddle.y, paddle.w, paddle.h);
}
function gameLoop() {
update();
render();
requestAnimationFrame(gameLoop);
}
// User Interactivity & Handover from Auto-play
function takeControl(clientX) {
if (isAutoPlay) {
isAutoPlay = false;
modeEl.innerText = '🎮 PLAYER MODE';
modeEl.style.color = '#00e676';
overlay.style.opacity = '0';
}
const rect = canvas.getBoundingClientRect();
paddle.targetX = (clientX - rect.left) - paddle.w / 2;
}
window.addEventListener('mousemove', (e) => {
takeControl(e.clientX);
});
window.addEventListener('touchmove', (e) => {
if (e.touches.length > 0) {
takeControl(e.touches[0].clientX);
}
}, { passive: true });
window.addEventListener('keydown', (e) => {
if (isAutoPlay) {
isAutoPlay = false;
modeEl.innerText = '🎮 PLAYER MODE';
modeEl.style.color = '#00e676';
overlay.style.opacity = '0';
}
const step = 35;
if (e.key === 'ArrowLeft' || e.key === 'a') {
paddle.targetX = Math.max(0, paddle.x - step);
} else if (e.key === 'ArrowRight' || e.key === 'd') {
paddle.targetX = Math.min(W - paddle.w, paddle.x + step);
}
});
window.addEventListener('pointerdown', (e) => {
takeControl(e.clientX);
});
// Boot
initGame();
requestAnimationFrame(gameLoop);
</script>
</body>
</html>