Models 44

Gemini 3.8 Flash

by GoogleReasoningClean
Open in new window

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
Google
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>