• Updated 30 Oct, 21:11 UTC
  • Next run 31 Oct, 05:17 UTCNext 31 Oct 05:17
  • Last 7 days: 4 new models · 475 runs7 d: 4 models · 475 runs
Playable Breakout

GPT-6.1 TerraOpenAI

Network offOpen alone (new tab)

Run details

Model
openai/gpt-6.1-terra
Route
OpenRouter API, one user message
Served by
OpenAI
Effort
medium, OpenRouter's default for this model
Limits
60 min · 128,000 output tokens (the model's limit)
Date
26 Oct 2026
Time
85 s
Size
21 kB
Tokens
83 in, 7,638 out (976 of them thinking)
List price
$0.038 at today's price ($1 in / $5 out per M)
Paid
$0.038

Raw files: output · meta.json

Exact prompt

Make a Breakout game I can play right now with the keyboard or the mouse. Give it several levels, a score and some juice.

It must be one complete, self-contained HTML file: inline all CSS and JavaScript, and make no network requests of any kind (no CDNs, web fonts or remote images). Reply with the file in a single ```html code block.

Source

21 kB 700 lines Raw

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Neon Breakout</title>
<style>
  :root {
    color-scheme: dark;
    font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    background: #080b18;
    color: #eef4ff;
  }
  * { box-sizing: border-box; }
  body {
    margin: 0;
    min-height: 100vh;
    display: grid;
    place-items: center;
    padding: 24px 14px;
    background:
      radial-gradient(circle at 20% 10%, #232253 0, transparent 32%),
      radial-gradient(circle at 85% 90%, #123044 0, transparent 30%),
      #080b18;
  }
  main { width: min(100%, 960px); }
  header {
    display: flex;
    justify-content: space-between;
    align-items: end;
    gap: 16px;
    margin-bottom: 16px;
  }
  h1 {
    margin: 0;
    font-size: clamp(1.5rem, 4vw, 2.4rem);
    letter-spacing: -.05em;
    line-height: 1;
  }
  h1 span { color: #67e8f9; }
  .subtitle { margin: 6px 0 0; color: #98a8c6; font-size: .9rem; }
  .stats { display: flex; gap: clamp(12px, 3vw, 30px); }
  .stat { text-align: right; }
  .stat small {
    display: block;
    color: #91a1be;
    font-size: .65rem;
    font-weight: 800;
    letter-spacing: .13em;
  }
  .stat strong {
    display: block;
    margin-top: 3px;
    font-size: clamp(1rem, 2.5vw, 1.35rem);
    font-variant-numeric: tabular-nums;
  }
  .game {
    position: relative;
    overflow: hidden;
    border: 1px solid #34436c;
    border-radius: 16px;
    background: #090f22;
    box-shadow: 0 24px 70px #0008, 0 0 35px #42d9ff10;
  }
  canvas {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 3 / 2;
    touch-action: none;
    cursor: crosshair;
  }
  .overlay {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    text-align: center;
    padding: 20px;
    background: #060b1aa8;
    pointer-events: none;
  }
  .overlay[hidden] { display: none; }
  .overlay-box {
    max-width: 440px;
    padding: 24px 30px;
    border: 1px solid #7084bc55;
    border-radius: 18px;
    background: #101a32e8;
    box-shadow: 0 12px 50px #0008;
  }
  .eyebrow {
    color: #67e8f9;
    font-size: .7rem;
    font-weight: 900;
    letter-spacing: .2em;
    text-transform: uppercase;
  }
  .overlay h2 {
    margin: 8px 0;
    font-size: clamp(1.5rem, 5vw, 2.5rem);
    letter-spacing: -.04em;
  }
  .overlay p { margin: 0; color: #b5c5e3; line-height: 1.5; }
  .overlay .hint { margin-top: 14px; color: #fff; font-size: .9rem; }
  .toolbar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 9px;
    margin-top: 14px;
  }
  button {
    border: 1px solid #47567a;
    border-radius: 9px;
    padding: 10px 15px;
    background: #192540;
    color: #edf6ff;
    font: inherit;
    font-size: .85rem;
    font-weight: 750;
    cursor: pointer;
  }
  button:hover { background: #26395c; }
  button:focus-visible { outline: 3px solid #67e8f9; outline-offset: 3px; }
  #playButton { background: #67e8f9; color: #071523; border-color: #67e8f9; }
  #playButton:hover { background: #a5f3fc; }
  .controls {
    margin: 0 0 0 auto;
    color: #9babc7;
    font-size: .8rem;
    line-height: 1.5;
  }
  kbd {
    padding: 2px 5px;
    border: 1px solid #435170;
    border-radius: 4px;
    background: #17213a;
    color: #dce9ff;
    font: inherit;
  }
  @media (max-width: 580px) {
    header { align-items: start; flex-direction: column; }
    .stats { width: 100%; justify-content: space-between; }
    .stat { text-align: left; }
    .controls { width: 100%; margin-top: 4px; }
    .overlay-box { padding: 14px 20px; }
    .overlay h2 { margin: 4px 0; }
    .overlay .hint { margin-top: 6px; }
  }
</style>
</head>
<body>
<main>
  <header>
    <div>
      <h1>NEON <span>BREAKOUT</span></h1>
      <p class="subtitle">Five levels. One more bounce.</p>
    </div>
    <div class="stats" aria-label="Game statistics">
      <div class="stat"><small>SCORE</small><strong id="score">0</strong></div>
      <div class="stat"><small>LEVEL</small><strong id="level">1 / 5</strong></div>
      <div class="stat"><small>LIVES</small><strong id="lives">3</strong></div>
    </div>
  </header>

  <div class="game">
    <canvas id="game" width="900" height="600"
      aria-label="Breakout game. Move the paddle with the mouse or arrow keys. Press space to launch."></canvas>
    <div class="overlay" id="overlay">
      <div class="overlay-box">
        <div class="eyebrow" id="overlayEyebrow">Ready to play?</div>
        <h2 id="overlayTitle">Break the glow.</h2>
        <p id="overlayText">Clear the bricks, keep the ball alive, and make it through all five levels.</p>
        <p class="hint" id="overlayHint">Click the board or press Space to start</p>
      </div>
    </div>
  </div>

  <div class="toolbar">
    <button id="playButton" type="button">Start game</button>
    <button id="restartButton" type="button">Restart</button>
    <button id="soundButton" type="button" aria-pressed="false">Sound: off</button>
    <p class="controls">
      Move: mouse / touch or <kbd>←</kbd> <kbd>→</kbd> &nbsp;·&nbsp;
      Launch: click or <kbd>Space</kbd> &nbsp;·&nbsp; Pause: <kbd>Esc</kbd>
    </p>
  </div>
</main>

<script>
(() => {
  "use strict";

  const canvas = document.getElementById("game");
  const ctx = canvas.getContext("2d");
  const scoreEl = document.getElementById("score");
  const levelEl = document.getElementById("level");
  const livesEl = document.getElementById("lives");
  const overlay = document.getElementById("overlay");
  const eyebrow = document.getElementById("overlayEyebrow");
  const title = document.getElementById("overlayTitle");
  const text = document.getElementById("overlayText");
  const hint = document.getElementById("overlayHint");
  const playButton = document.getElementById("playButton");
  const restartButton = document.getElementById("restartButton");
  const soundButton = document.getElementById("soundButton");

  const W = canvas.width, H = canvas.height, TOTAL_LEVELS = 5;
  const keys = { left: false, right: false };
  const paddle = { x: W / 2 - 58, y: 548, w: 116, h: 14, speed: 660 };
  const ball = { x: W / 2, y: 0, vx: 0, vy: 0, r: 8 };
  const palette = ["#ff6b9d", "#ffaf6b", "#ffe078", "#72f1c8", "#66d9ff", "#b497ff"];
  const stars = Array.from({ length: 55 }, (_, i) => ({
    x: (i * 137.5 + 23) % W,
    y: (i * 83.7 + 31) % H,
    r: i % 7 === 0 ? 1.5 : 0.8
  }));

  let state, score, level, lives, bricks, particles, trail, serving;
  let shake = 0, flash = 0, soundEnabled = false, audioContext = null;
  let lastTime = 0, accumulator = 0;

  function clamp(n, min, max) { return Math.max(min, Math.min(max, n)); }

  function beep(frequency, duration = 0.06, type = "sine", volume = 0.035) {
    if (!soundEnabled) return;
    try {
      audioContext ||= new (window.AudioContext || window.webkitAudioContext)();
      if (audioContext.state === "suspended") audioContext.resume();
      const oscillator = audioContext.createOscillator();
      const gain = audioContext.createGain();
      oscillator.type = type;
      oscillator.frequency.setValueAtTime(frequency, audioContext.currentTime);
      gain.gain.setValueAtTime(volume, audioContext.currentTime);
      gain.gain.exponentialRampToValueAtTime(0.001, audioContext.currentTime + duration);
      oscillator.connect(gain);
      gain.connect(audioContext.destination);
      oscillator.start();
      oscillator.stop(audioContext.currentTime + duration);
    } catch (_) {
      // The game remains playable if audio is unavailable.
    }
  }

  function updateHUD() {
    scoreEl.textContent = score.toLocaleString();
    levelEl.textContent = `${level} / ${TOTAL_LEVELS}`;
    livesEl.textContent = lives;
  }

  function setOverlay(kind) {
    overlay.hidden = kind === "playing";
    if (kind === "ready") {
      eyebrow.textContent = "Ready to play?";
      title.textContent = "Break the glow.";
      text.textContent = "Clear the bricks, keep the ball alive, and make it through all five levels.";
      hint.textContent = "Click the board or press Space to start";
    } else if (kind === "paused") {
      eyebrow.textContent = "Take a breath";
      title.textContent = "Paused";
      text.textContent = "Your game is right where you left it.";
      hint.textContent = "Press Escape or click Resume";
    } else if (kind === "over") {
      eyebrow.textContent = "Game over";
      title.textContent = "Nice run.";
      text.textContent = `You scored ${score.toLocaleString()} points.`;
      hint.textContent = "Click the board or press Space to try again";
    } else if (kind === "won") {
      eyebrow.textContent = "All levels cleared";
      title.textContent = "You did it!";
      text.textContent = `Final score: ${score.toLocaleString()} points.`;
      hint.textContent = "Click the board or press Space to play again";
    }
    playButton.textContent = kind === "playing" ? "Pause" :
      kind === "paused" ? "Resume" :
      kind === "ready" ? "Start game" : "Play again";
  }

  function buildLevel(n) {
    const result = [];
    const cols = 10, rows = 6, bw = 78, bh = 21, gap = 8;
    const startX = (W - (cols * bw + (cols - 1) * gap)) / 2;
    for (let row = 0; row < rows; row++) {
      for (let col = 0; col < cols; col++) {
        let include = true;
        if (n === 2) include = !(row >= 3 && (col === 0 || col === 9));
        if (n === 3) include = (row + col) % 5 !== 0;
        if (n === 4) include = !(row >= 2 && (col === 2 || col === 7) && row % 2 === 0);
        if (n === 5) include = !((row === 3 || row === 4) && (col === 4 || col === 5));
        if (!include) continue;
        const hp = n >= 2 && row < Math.min(4, n - 1) && (col + row + n) % 3 !== 0 ? 2 : 1;
        result.push({
          x: startX + col * (bw + gap),
          y: 85 + row * (bh + gap),
          w: bw, h: bh, hp, maxHp: hp,
          color: palette[(row + n - 1) % palette.length]
        });
      }
    }
    return result;
  }

  function attachBall() {
    ball.x = paddle.x + paddle.w / 2;
    ball.y = paddle.y - ball.r - 2;
    ball.vx = ball.vy = 0;
    serving = true;
    trail = [];
  }

  function reset() {
    state = "ready";
    score = 0;
    level = 1;
    lives = 3;
    paddle.x = W / 2 - paddle.w / 2;
    bricks = buildLevel(level);
    particles = [];
    shake = flash = 0;
    keys.left = keys.right = false;
    attachBall();
    updateHUD();
    setOverlay(state);
  }

  function start() {
    state = "playing";
    setOverlay(state);
  }

  function launch() {
    if (!serving || state !== "playing") return;
    const speed = 390 + (level - 1) * 28;
    const angle = (Math.random() * 0.5 - 0.25);
    ball.vx = Math.sin(angle) * speed;
    ball.vy = -Math.cos(angle) * speed;
    serving = false;
    beep(440, 0.08, "triangle");
  }

  function pauseToggle() {
    if (state === "playing") {
      state = "paused";
      keys.left = keys.right = false;
      setOverlay(state);
    } else if (state === "paused") {
      state = "playing";
      setOverlay(state);
    }
  }

  function action() {
    if (state === "ready") {
      start();
      launch();
    } else if (state === "over" || state === "won") {
      reset();
      start();
      launch();
    } else if (state === "playing") {
      launch();
    }
  }

  function burst(x, y, color, count = 10) {
    for (let i = 0; i < count; i++) {
      const angle = Math.random() * Math.PI * 2;
      const speed = 40 + Math.random() * 200;
      const life = 0.3 + Math.random() * 0.45;
      particles.push({
        x, y, vx: Math.cos(angle) * speed, vy: Math.sin(angle) * speed,
        life, maxLife: life, size: 2 + Math.random() * 4, color
      });
    }
  }

  function nextLevel() {
    score += 500 * level;
    if (level === TOTAL_LEVELS) {
      state = "won";
      burst(W / 2, H / 2, "#67e8f9", 35);
      beep(880, 0.3, "triangle");
      updateHUD();
      setOverlay(state);
      return;
    }
    level++;
    bricks = buildLevel(level);
    paddle.x = W / 2 - paddle.w / 2;
    attachBall();
    flash = 0.5;
    beep(660, 0.18, "triangle");
    updateHUD();
  }

  function movePointer(event) {
    const rect = canvas.getBoundingClientRect();
    const x = (event.clientX - rect.left) * W / rect.width;
    paddle.x = clamp(x - paddle.w / 2, 8, W - paddle.w - 8);
    if (serving) {
      ball.x = paddle.x + paddle.w / 2;
      ball.y = paddle.y - ball.r - 2;
    }
  }

  canvas.addEventListener("pointermove", movePointer);
  canvas.addEventListener("pointerdown", event => {
    event.preventDefault();
    movePointer(event);
    if (canvas.setPointerCapture) canvas.setPointerCapture(event.pointerId);
    action();
  });

  playButton.addEventListener("click", () => {
    if (state === "playing" || state === "paused") pauseToggle();
    else {
      if (state === "over" || state === "won") reset();
      start();
    }
  });
  restartButton.addEventListener("click", () => {
    reset();
    start();
  });
  soundButton.addEventListener("click", () => {
    soundEnabled = !soundEnabled;
    soundButton.textContent = `Sound: ${soundEnabled ? "on" : "off"}`;
    soundButton.setAttribute("aria-pressed", String(soundEnabled));
    if (soundEnabled) beep(660, 0.1, "triangle");
  });

  window.addEventListener("keydown", event => {
    const key = event.key.toLowerCase();
    if (["arrowleft", "arrowright", "a", "d"].includes(key)) {
      if (key === "arrowleft" || key === "arrowright") event.preventDefault();
      if (key === "arrowleft" || key === "a") keys.left = true;
      if (key === "arrowright" || key === "d") keys.right = true;
    } else if (key === " " && event.target.tagName !== "BUTTON") {
      event.preventDefault();
      if (!event.repeat) action();
    } else if (key === "escape" && !event.repeat) {
      pauseToggle();
    }
  });
  window.addEventListener("keyup", event => {
    const key = event.key.toLowerCase();
    if (key === "arrowleft" || key === "a") keys.left = false;
    if (key === "arrowright" || key === "d") keys.right = false;
  });
  window.addEventListener("blur", () => {
    keys.left = keys.right = false;
    if (state === "playing") pauseToggle();
  });

  function update(dt) {
    if (state !== "playing") return;

    const direction = (keys.right ? 1 : 0) - (keys.left ? 1 : 0);
    paddle.x = clamp(paddle.x + direction * paddle.speed * dt, 8, W - paddle.w - 8);

    for (const p of particles) {
      p.x += p.vx * dt;
      p.y += p.vy * dt;
      p.vy += 160 * dt;
      p.life -= dt;
    }
    particles = particles.filter(p => p.life > 0);
    shake = Math.max(0, shake - dt * 18);
    flash = Math.max(0, flash - dt * 1.6);

    if (serving) {
      ball.x = paddle.x + paddle.w / 2;
      ball.y = paddle.y - ball.r - 2;
      return;
    }

    const oldX = ball.x, oldY = ball.y;
    ball.x += ball.vx * dt;
    ball.y += ball.vy * dt;

    if (ball.x - ball.r < 8) {
      ball.x = 8 + ball.r;
      ball.vx = Math.abs(ball.vx);
      beep(250);
    } else if (ball.x + ball.r > W - 8) {
      ball.x = W - 8 - ball.r;
      ball.vx = -Math.abs(ball.vx);
      beep(250);
    }
    if (ball.y - ball.r < 8) {
      ball.y = 8 + ball.r;
      ball.vy = Math.abs(ball.vy);
      beep(280);
    }

    if (ball.vy > 0 &&
        oldY + ball.r <= paddle.y + 4 &&
        ball.y + ball.r >= paddle.y &&
        ball.x + ball.r >= paddle.x &&
        ball.x - ball.r <= paddle.x + paddle.w) {
      ball.y = paddle.y - ball.r;
      const offset = clamp((ball.x - (paddle.x + paddle.w / 2)) / (paddle.w / 2), -1, 1);
      const speed = Math.min(650, Math.hypot(ball.vx, ball.vy) + 3);
      const angle = offset * 1.12;
      ball.vx = Math.sin(angle) * speed;
      ball.vy = -Math.cos(angle) * speed;
      burst(ball.x, paddle.y, "#67e8f9", 6);
      beep(360 + Math.abs(offset) * 180, 0.06, "triangle");
    }

    for (let i = bricks.length - 1; i >= 0; i--) {
      const b = bricks[i];
      const nearestX = clamp(ball.x, b.x, b.x + b.w);
      const nearestY = clamp(ball.y, b.y, b.y + b.h);
      const dx = ball.x - nearestX, dy = ball.y - nearestY;
      if (dx * dx + dy * dy > ball.r * ball.r) continue;

      if (oldY + ball.r <= b.y) {
        ball.y = b.y - ball.r;
        ball.vy = -Math.abs(ball.vy);
      } else if (oldY - ball.r >= b.y + b.h) {
        ball.y = b.y + b.h + ball.r;
        ball.vy = Math.abs(ball.vy);
      } else if (oldX + ball.r <= b.x) {
        ball.x = b.x - ball.r;
        ball.vx = -Math.abs(ball.vx);
      } else if (oldX - ball.r >= b.x + b.w) {
        ball.x = b.x + b.w + ball.r;
        ball.vx = Math.abs(ball.vx);
      } else {
        ball.vy *= -1;
      }

      b.hp--;
      score += 50;
      burst(ball.x, ball.y, b.color, b.hp === 0 ? 12 : 5);
      shake = b.hp === 0 ? 3 : 1.5;
      beep(b.hp === 0 ? 520 + (i % 5) * 60 : 220, 0.07, "triangle");
      if (b.hp <= 0) {
        score += 50;
        bricks.splice(i, 1);
      }
      updateHUD();
      if (bricks.length === 0) nextLevel();
      break;
    }

    if (state !== "playing" || serving) return;

    if (ball.y - ball.r > H) {
      lives--;
      shake = 8;
      flash = 0.35;
      beep(120, 0.25, "sawtooth");
      updateHUD();
      if (lives <= 0) {
        state = "over";
        setOverlay(state);
      } else {
        attachBall();
      }
    }

    if (!serving && state === "playing") {
      trail.push({ x: ball.x, y: ball.y });
      if (trail.length > 12) trail.shift();
    }
  }

  function roundedRect(x, y, w, h, r) {
    ctx.beginPath();
    ctx.roundRect(x, y, w, h, r);
  }

  function render(time) {
    ctx.clearRect(0, 0, W, H);
    ctx.save();
    if (shake > 0 && state === "playing") {
      ctx.translate((Math.random() - 0.5) * shake, (Math.random() - 0.5) * shake);
    }

    const bg = ctx.createLinearGradient(0, 0, 0, H);
    bg.addColorStop(0, "#111b38");
    bg.addColorStop(1, "#080d1e");
    ctx.fillStyle = bg;
    ctx.fillRect(-10, -10, W + 20, H + 20);

    ctx.strokeStyle = "#ffffff08";
    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();
    }
    for (const s of stars) {
      ctx.fillStyle = `rgba(190, 220, 255, ${0.15 + 0.12 * Math.sin(time / 900 + s.x)})`;
      ctx.beginPath(); ctx.arc(s.x, s.y, s.r, 0, Math.PI * 2); ctx.fill();
    }

    ctx.fillStyle = "#7f9bc9";
    ctx.globalAlpha = 0.7;
    ctx.font = "bold 12px system-ui, sans-serif";
    ctx.letterSpacing = "2px";
    ctx.fillText(`LEVEL ${level} / ${TOTAL_LEVELS}`, 26, 40);
    ctx.textAlign = "right";
    ctx.fillText(`${bricks.length} BRICKS LEFT`, W - 26, 40);
    ctx.textAlign = "left";
    ctx.globalAlpha = 1;

    for (const b of bricks) {
      ctx.save();
      ctx.shadowColor = b.color;
      ctx.shadowBlur = 12;
      ctx.fillStyle = b.color;
      roundedRect(b.x, b.y, b.w, b.h, 5);
      ctx.fill();
      ctx.shadowBlur = 0;
      ctx.fillStyle = "#ffffff55";
      roundedRect(b.x + 3, b.y + 3, b.w - 6, 4, 2);
      ctx.fill();
      if (b.hp > 1) {
        ctx.fillStyle = "#14203b99";
        roundedRect(b.x + b.w / 2 - 10, b.y + 9, 20, 6, 3);
        ctx.fill();
      }
      ctx.restore();
    }

    for (const p of particles) {
      ctx.globalAlpha = clamp(p.life / p.maxLife, 0, 1);
      ctx.fillStyle = p.color;
      ctx.fillRect(p.x, p.y, p.size, p.size);
    }
    ctx.globalAlpha = 1;

    for (let i = 0; i < trail.length; i++) {
      ctx.globalAlpha = (i / trail.length) * 0.3;
      ctx.fillStyle = "#8cefff";
      ctx.beginPath();
      ctx.arc(trail[i].x, trail[i].y, ball.r * (i / trail.length), 0, Math.PI * 2);
      ctx.fill();
    }
    ctx.globalAlpha = 1;

    ctx.save();
    ctx.shadowColor = "#55e7ff";
    ctx.shadowBlur = 22;
    const pg = ctx.createLinearGradient(paddle.x, 0, paddle.x + paddle.w, 0);
    pg.addColorStop(0, "#53a8ff");
    pg.addColorStop(0.5, "#b3fbff");
    pg.addColorStop(1, "#53a8ff");
    ctx.fillStyle = pg;
    roundedRect(paddle.x, paddle.y, paddle.w, paddle.h, 7);
    ctx.fill();

    ctx.shadowColor = "#fff";
    ctx.shadowBlur = 18;
    ctx.fillStyle = "#fff";
    ctx.beginPath();
    ctx.arc(ball.x, ball.y, ball.r, 0, Math.PI * 2);
    ctx.fill();
    ctx.restore();

    if (serving && state === "playing") {
      ctx.fillStyle = "#b8cbea";
      ctx.textAlign = "center";
      ctx.font = "bold 13px system-ui, sans-serif";
      ctx.fillText("CLICK OR PRESS SPACE TO LAUNCH", W / 2, H - 20);
      ctx.textAlign = "left";
    }

    if (flash > 0) {
      ctx.fillStyle = `rgba(120, 220, 255, ${flash * 0.3})`;
      ctx.fillRect(0, 0, W, H);
    }
    ctx.restore();
  }

  function frame(time) {
    if (!lastTime) lastTime = time;
    const elapsed = Math.min((time - lastTime) / 1000, 0.05);
    lastTime = time;
    accumulator += elapsed;
    const step = 1 / 120;
    while (accumulator >= step) {
      update(step);
      accumulator -= step;
    }
    render(time);
    requestAnimationFrame(frame);
  }

  reset();
  requestAnimationFrame(frame);
})();
</script>
</body>
</html>

Compare with

GPT-6.1 Terra: other attempts