Models 44

Nemotron 3.5 Lightning (free)

by NVIDIAReasoning1 console error
Open in new window

Running live in a sandboxed frame. Click inside it before using the keyboard.

How it went

Total time
1 min 1 s
Cost
$0
Output tokens
4,479
Spent thinking
0 tokens
Speed
73.2 tok/s
Console errors
1
First token after
286 ms
First visible text after
286 ms
Prompt tokens
531
Code size
14.7 KB
Finish reason
stop
Served by
Nvidia
Model id
nvidia/nemotron-3.5-lightning:free
Reasoning sent
{"effort":"none"}
Max output
32,000 tokens
Generated
Nov 9, 2026

Console errors

Caught in the first 3 seconds after load, in a sandboxed iframe like the one above.

Identifier 'paddleWidth' has already been declared

What it was asked

The prompt
Build a polished Breakout (brick breaker) game in a single HTML file using vanilla JavaScript and a <canvas>. Requirements: - A paddle controlled with the mouse and with the left/right arrow keys. - The bounce angle off the paddle depends on where the ball hits it (center = straight up, edges = sharp angle). - One level with at least 6 rows of bricks, mixing normal bricks and tougher bricks that need 2 hits and visibly crack after the first one. - Some bricks visibly carry a power-up icon; when broken they drop it, and catching it with the paddle gives either a wider paddle (10 seconds) or multi-ball (3 balls). - The ball must never pass through bricks or the paddle. - Particles when a brick breaks. - 3 lives, score displayed. Game over and victory screens with a restart option.
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 · 372 lines

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Breakout</title>
  <style>
    *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
    html, body { height: 100%; overflow: hidden; background: #1a1a2e; }
    canvas { display: block; }
    #ui { position: absolute; top: 10px; left: 10px; right: 10px; display: flex; justify-content: space-between; align-items: flex-start; color: #e0e0e0; font-family: 'Segoe UI', system-ui, sans-serif; pointer-events: none; }
    #ui > div { pointer-events: auto; }
    #score { font-size: 1rem; }
    #lives { font-size: 1rem; color: #ff5f57; }
    #highscore { font-size: 0.8rem; color: #a0a0a0; }
    #title { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: #e0e0e0; font-family: 'Segoe UI', system-ui, sans-serif; font-size: 2rem; text-align: center; pointer-events: none; }
    #screen { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: #1a1a2e; display: none; align-items: center; justify-content: center; flex-direction: column; gap: 1rem; pointer-events: auto; }
    #screen.active { display: flex; }
    button { background: #e94560; color: white; border: none; padding: 0.8rem 1.5rem; font-size: 1rem; cursor: pointer; border-radius: 4px; transition: background 0.2s; font-family: inherit; }
    button:hover { background: #ff6b8a; }
    button:focus { outline: 2px solid #fff; outline-offset: 2px; }
    #start { top: 40%; }
    #gameover { top: 40%; }
    #victory { top: 40%; }
    .powerup { position: absolute; width: 20px; height: 20px; border-radius: 3px; pointer-events: none; }
    .powerup.fire { background: #ffd700; box-shadow: 0 0 8px #ffd700; }
    .powerup.multi { background: #00bfff; box-shadow: 0 0 8px #00bfff; }
  </style>
</head>
<body>
  <canvas id="canvas"></canvas>
  <div id="ui">
    <div>
      <span id="score">Score: 0</span>
      <span id="highscore">High: 0</span>
    </div>
    <div>
      <span id="lives">Lives: 3</span>
    </div>
  </div>
  <div id="title">Breakout</div>
  <div id="screen" class="start" role="dialog">
    <button id="startBtn">Click or press a key to start</button>
  </div>
  <div id="screen" class="gameover" role="dialog">
    <span>Game Over</span>
    <button id="restartBtn">Restart</button>
  </div>
  <div id="screen" class="victory" role="dialog">
    <span>Victory!</span>
    <button id="restartBtn">Play Again</button>
  </div>

  <script>
    (() => {
      const canvas = document.getElementById('canvas');
      const ctx = canvas.getContext('2d');
      const scoreEl = document.getElementById('score');
      const livesEl = document.getElementById('lives');
      const highscoreEl = document.getElementById('highscore');
      const startBtn = document.getElementById('startBtn');
      const restartBtn = document.getElementById('restartBtn');
      const screens = document.querySelectorAll('#screen');

      let W, H, paddleWidth, paddleHeight, brickRowCount = 6, brickColumnCount, brickWidth, brickHeight, brickPadding, brickOffsetTop, brickOffsetLeft, score = 0, highScore = parseInt(localStorage.getItem('breakoutHigh') || '0'), lives = 3, gameState = 'title', keys = { left: false, right: false }, particles = [], powerUps = [], balls = [], activePowerUp = null, powerUpTimer = 0;

      function resize() {
        const maxW = 1280, maxH = 800;
        let cW = window.innerWidth, cH = window.innerHeight;
        if (cW > maxW) cW = maxW;
        if (cH > maxH) cH = maxH;
        const ratio = Math.min(cW / maxW, cH / maxH);
        W = Math.floor(800 * ratio);
        H = Math.floor(450 * ratio);
        canvas.width = W;
        canvas.height = H;
        initGame();
      }
      window.addEventListener('resize', resize);
      resize();

      const bricks = [];
      function initBricks() {
        bricks.length = 0;
        brickColumnCount = Math.floor((W - 40) / (brickWidth + brickPadding)) || 1;
        brickRowCount = Math.min(brickRowCount, Math.floor((H - 80) / (brickHeight + brickPadding)) || 1);
        brickWidth = (W - 40 - (brickColumnCount - 1) * brickPadding) / brickColumnCount;
        brickHeight = 20;
        brickPadding = 4;
        brickOffsetTop = 50;
        brickOffsetLeft = 20;
        for (let c = 0; c < brickColumnCount; c++) {
          bricks[c] = [];
          for (let r = 0; r < brickRowCount; r++) {
            const hitCount = (r % 2 === 0) ? 1 : 2;
            bricks[c][r] = { x: 0, y: 0, status: hitCount, hit: 0, type: hitCount > 1 ? 'tough' : 'normal' };
          }
        }
      }

      function drawBricks() {
        for (let c = 0; c < brickColumnCount; c++) {
          for (let r = 0; r < brickRowCount; r++) {
            if (bricks[c][r].status <= 0) continue;
            const b = bricks[c][r];
            const x = c * (brickWidth + brickPadding) + brickOffsetLeft;
            const y = r * (brickHeight + brickPadding) + brickOffsetTop;
            ctx.fillStyle = b.type === 'tough' ? '#ff6b6b' : '#ffa3a3';
            ctx.shadowColor = '#ff6b6b';
            ctx.shadowBlur = 8;
            ctx.fillRect(x, y, brickWidth, brickHeight);
            ctx.shadowBlur = 0;
            // power-up icon
            if (Math.random() < 0.2 && b.status === b.hitCount) {
              const icons = ['fire', 'multi'];
              const icon = icons[Math.floor(Math.random() * icons.length)];
              const ix = x + brickWidth / 2 - 5;
              const iy = y + brickHeight / 2 - 5;
              powerUps.push({ x: ix, y: iy, type: icon, width: 10, height: 10 });
            }
            // crack after first hit on tough bricks
            if (b.type === 'tough' && b.hit >= 1) {
              ctx.strokeStyle = 'rgba(255,255,255,0.3)';
              ctx.lineWidth = 2;
              ctx.beginPath();
              ctx.moveTo(x + 4, y + 4);
              ctx.lineTo(x + brickWidth - 4, y + brickHeight - 4);
              ctx.moveTo(x + brickWidth - 4, y + 4);
              ctx.lineTo(x + 4, y + brickHeight - 4);
              ctx.stroke();
            }
          }
        }
      }

      function drawPaddle() {
        ctx.fillStyle = '#4ecdc4';
        ctx.shadowColor = '#4ecdc4';
        ctx.shadowBlur = 12;
        ctx.fillRect(paddleX, paddleY, paddleWidth, paddleHeight);
        ctx.shadowBlur = 0;
      }

      let paddleX = (W - 150) / 2, paddleY = H - 30, paddleWidth = 150, paddleHeight = 12;

      function drawBall(ball) {
        ctx.fillStyle = ball.color;
        ctx.shadowColor = ball.color;
        ctx.shadowBlur = 15;
        ctx.beginPath();
        ctx.arc(ball.x, ball.y, ball.r, 0, Math.PI * 2);
        ctx.fill();
        ctx.shadowBlur = 0;
      }

      function drawParticles() {
        particles.forEach(p => {
          ctx.fillStyle = p.color;
          ctx.globalAlpha = p.alpha;
          ctx.fillRect(p.x, p.y, p.w, p.h);
          p.alpha -= 0.02;
          p.x += p.vx;
          p.y += p.vy;
        });
        particles = particles.filter(p => p.alpha > 0);
        ctx.globalAlpha = 1;
      }

      function drawPowerUps() {
        powerUps.forEach(p => {
          const color = p.type === 'fire' ? '#ffd700' : '#00bfff';
          ctx.fillStyle = color;
          ctx.shadowColor = color;
          ctx.shadowBlur = 8;
          ctx.fillRect(p.x, p.y, p.width, p.height);
          ctx.shadowBlur = 0;
        });
      }

      function draw() {
        ctx.clearRect(0, 0, W, H);
        drawBricks();
        drawParticles();
        drawPowerUps();
        drawPaddle();
        balls.forEach(b => drawBall(b));
        // UI
        ctx.fillStyle = '#e0e0e0';
        ctx.font = '16px Segoe UI';
        ctx.fillText(`Score: ${score}`, 20, 30);
        ctx.fillText(`Lives: ${lives}`, W - 100, 30);
      }

      function spawnBall(x, y, vx, vy, color = '#ffd700') {
        balls.push({ x, y, r: 8, vx, vy, color, launched: false });
      }

      let ballX, ballY, ballVX, ballVY;
      spawnBall(W / 2, H / 2, 3, -3);

      function collisionDetection() {
        // paddle
        for (const ball of balls) {
          if (ball.launched) {
            if (ball.y + ball.r > paddleY && ball.y - ball.r < paddleY + paddleHeight && ball.x > paddleX && ball.x < paddleX + paddleWidth) {
              const hitPos = (ball.x - paddleX) / paddleWidth;
              const angle = (hitPos - 0.5) * Math.PI / 3;
              ball.vx = Math.cos(angle) * 4;
              ball.vy = -Math.sin(angle) * 4;
              if (Math.abs(ball.vx) < 2) ball.vx = 2 * (ball.vx > 0 ? 1 : -1);
            }
            if (ball.y + ball.r > H) {
              lives--;
              livesEl.textContent = `Lives: ${lives}`;
              if (lives <= 0) gameOver();
              else {
                ball.launched = false;
                ballX = paddleX + paddleWidth / 2;
                ballY = paddleY - 8;
              }
            }
            // bricks
            for (let c = 0; c < brickColumnCount; c++) {
              for (let r = 0; r < brickRowCount; r++) {
                if (bricks[c][r].status <= 0) continue;
                const b = bricks[c][r];
                const x = c * (brickWidth + brickPadding) + brickOffsetLeft;
                const y = r * (brickHeight + brickPadding) + brickOffsetTop;
                if (ball.x + ball.r > x && ball.x - ball.r < x + brickWidth && ball.y + ball.r > y && ball.y - ball.r < y + brickHeight) {
                  ball.vy = -ball.vy;
                  b.hit++;
                  b.status--;
                  // particles
                  for (let i = 0; i < 15; i++) {
                    particles.push({ x: b.x + brickWidth / 2, y: b.y + brickHeight / 2, w: 4, h: 4, color: b.type === 'tough' ? '#ff6b6b' : '#ffa3a3', alpha: 1, vx: (Math.random() - 0.5) * 6, vy: (Math.random() - 0.5) * 6 });
                  }
                  // power-up drop
                  if (Math.random() < 0.3 && b.type === 'normal') {
                    const puType = Math.random() < 0.5 ? 'fire' : 'multi';
                    powerUps.push({ x: b.x + brickWidth / 2 - 5, y: b.y + brickHeight / 2 - 5, type: puType, width: 10, height: 10 });
                  }
                  if (b.status <= 0) {
                    score += 10;
                    scoreEl.textContent = `Score: ${score}`;
                  }
                  break;
                }
              }
            }
          }
        }
        // power-up catch
        powerUps.forEach((pu, pi) => {
          for (const ball of balls) {
            if (ball.launched && ball.x > pu.x && ball.x < pu.x + pu.width && ball.y + ball.r > pu.y && ball.y - ball.r < pu.y + pu.height) {
              if (pu.type === 'fire') {
                paddleWidth = Math.min(paddleWidth + 30, 300);
                powerUpTimer = 1000;
                activePowerUp = 'wide';
              } else if (pu.type === 'multi') {
                // add two extra balls
                const b1 = { x: ball.x, y: ball.y, r: 8, vx: ball.vx + (Math.random() - 0.5) * 2, vy: ball.vy, color: '#ffd700', launched: true };
                const b2 = { x: ball.x, y: ball.y, r: 8, vx: ball.vx - (Math.random() - 0.5) * 2, vy: ball.vy, color: '#ffd700', launched: true };
                balls.push(b1, b2);
              }
              powerUps.splice(pi, 1);
            }
          }
        });
        // wall collisions
        for (const ball of balls) {
          if (ball.x + ball.r > W - 20) { ball.vx = -Math.abs(ball.vx); ball.x = W - 20 - ball.r; }
          if (ball.x - ball.r < 20) { ball.vx = Math.abs(ball.vx); ball.x = 20 + ball.r; }
          if (ball.y - ball.r < 20) { ball.vy = Math.abs(ball.vy); ball.y = 20 + ball.r; }
        }
      }

      function gameLoop() {
        if (gameState !== 'play') return;
        // power-up timer
        if (activePowerUp) {
          powerUpTimer -= 16;
          if (powerUpTimer <= 0) {
            paddleWidth = Math.max(paddleWidth - 30, 150);
            activePowerUp = null;
          }
        }
        // move paddle with keys
        if (keys.left) paddleX = Math.max(20, paddleX - 5);
        if (keys.right) paddleX = Math.min(W - paddleWidth - 20, paddleX + 5);
        // mouse
        document.addEventListener('mousemove', e => {
          const rect = canvas.getBoundingClientRect();
          const mouseX = e.clientX - rect.left - canvas.clientLeft;
          paddleX = mouseX - paddleWidth / 2;
          paddleX = Math.max(20, Math.min(W - paddleWidth - 20, paddleX));
        });
        // move balls
        balls.forEach(ball => {
          if (!ball.launched) {
            ball.x = paddleX + paddleWidth / 2;
            ball.y = paddleY - ball.r;
            if (gameState === 'play') ball.launched = true;
          } else {
            ball.x += ball.vx;
            ball.y += ball.vy;
          }
        });
        collisionDetection();
        draw();
        requestAnimationFrame(gameLoop);
      }

      function startGame() {
        gameState = 'play';
        lives = 3;
        score = 0;
        livesEl.textContent = `Lives: ${lives}`;
        scoreEl.textContent = `Score: ${score}`;
        initBricks();
        balls.length = 0;
        powerUps.length = 0;
        particles.length = 0;
        paddleWidth = 150;
        activePowerUp = null;
        powerUpTimer = 0;
        balls.push({ x: W / 2, y: H / 2, r: 8, vx: 3, vy: -3, color: '#ffd700', launched: false });
        gameScreen('none');
      }

      function gameOver() {
        gameState = 'over';
        highScore = Math.max(score, highScore);
        localStorage.setItem('breakoutHigh', highScore);
        highscoreEl.textContent = `High: ${highScore}`;
        gameScreen('flex');
      }

      function victory() {
        gameState = 'win';
        highScore = Math.max(score, highScore);
        localStorage.setItem('breakoutHigh', highScore);
        highscoreEl.textContent = `High: ${highScore}`;
        gameScreen('flex');
      }

      function gameScreen(display) {
        screens.forEach(s => s.style.display = 'none');
        document.getElementById(gameState === 'over' ? 'gameover' : gameState === 'win' ? 'victory' : 'start').style.display = display;
      }

      // events
      startBtn.addEventListener('click', () => { startGame(); });
      restartBtn.addEventListener('click', startGame);
      document.addEventListener('keydown', e => {
        if (e.key === 'ArrowLeft') keys.left = true;
        if (e.key === 'ArrowRight') keys.right = true;
        if (e.key === ' ' || e.key === 'Enter') { e.preventDefault(); if (gameState === 'title') startGame(); }
      });
      document.addEventListener('keyup', e => {
        if (e.key === 'ArrowLeft') keys.left = false;
        if (e.key === 'ArrowRight') keys.right = false;
      });

      // init
      let brickWidth, brickHeight, brickPadding;
      initBricks();
      gameLoop();
    })();
  </script>
</body>
</html>