Models 44

Dots3-Note Preview (free)

by Dots StudioReasoningClean
Open in new window

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

How it went

Total time
37.4 s
Cost
$0
Output tokens
3,676
Spent thinking
0 tokens
Speed
100.1 tok/s
Console errors
0
First token after
709 ms
First visible text after
709 ms
Prompt tokens
359
Code size
11.5 KB
Finish reason
stop
Served by
AtlasCloud
Model id
dots-studio/dots-3-note-preview:free
Reasoning sent
{"effort":"none"}
Max output
32,000 tokens
Generated
Nov 9, 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 · 411 lines

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hamburger Breakout – Hearts Explosion</title>
<style>
  * { margin:0; padding:0; box-sizing:border-box; }
  html,body { height:100%; background:#1a1a2e; color:#fff; font-family:'Arial Black',Arial,sans-serif; overflow:hidden; }
  #wrap { position:relative; width:100vw; height:100vh; display:flex; align-items:center; justify-content:center; }
  canvas { display:block; background:#16213e; border-radius:12px; box-shadow:0 0 40px rgba(255,105,180,.4); cursor:none; }
  #overlay { position:absolute; inset:0; display:flex; flex-direction:column; align-items:center; justify-content:center; text-align:center; background:rgba(0,0,0,.55); backdrop-filter:blur(4px); z-index:10; }
  #overlay h1 { font-size:clamp(28px,6vw,64px); color:#ff6b9d; text-shadow:0 0 15px #ff6b9d; margin-bottom:10px; }
  #overlay p { font-size:clamp(16px,3vw,24px); margin-bottom:30px; color:#ffd166; }
  #overlay button { padding:14px 36px; font-size:clamp(16px,3vw,22px); background:#ff6b9d; border:none; border-radius:50px; color:#fff; cursor:pointer; box-shadow:0 0 20px #ff6b9d; transition:transform .2s; }
  #overlay button:hover { transform:scale(1.05); }
  .hidden { display:none !important; }
</style>
</head>
<body>
<div id="wrap">
  <canvas id="game"></canvas>
  <div id="overlay">
    <h1>🍔 HAMBURGER BREAKOUT 🍔</h1>
    <p>Break bricks, collect hearts, survive the sizzle!</p>
    <button id="startBtn">Click or Press a Key to Start</button>
  </div>
</div>

<script>
(() => {
  const canvas = document.getElementById('game');
  const ctx = canvas.getContext('2d');
  const overlay = document.getElementById('overlay');
  const startBtn = document.getElementById('startBtn');

  let W, H;
  function resize() {
    const maxW = Math.min(1280, window.innerWidth - 40);
    const maxH = Math.min(800, window.innerHeight - 40);
    W = maxW; H = maxH;
    canvas.width = W; canvas.height = H;
  }
  window.addEventListener('resize', resize);
  resize();

  // ---------- GAME STATE ----------
  let bricks = [];
  let hearts = [];
  let particles = [];
  let paddle, ball;
  let score = 0;
  let lives = 3;
  let level = 1;
  let running = false;
  let autoPlay = true;
  let lastTime = 0;

  // ---------- CLASSES ----------
  class Paddle {
    constructor() {
      this.w = Math.max(100, W * 0.18);
      this.h = 24;
      this.x = W / 2 - this.w / 2;
      this.y = H - 60;
      this.speed = 10;
    }
    draw() {
      // bun
      ctx.fillStyle = '#d2691e';
      ctx.beginPath();
      ctx.ellipse(this.x + this.w/2, this.y + 8, this.w/2, 10, 0, 0, Math.PI*2);
      ctx.fill();
      // patty
      ctx.fillStyle = '#5d4037';
      ctx.fillRect(this.x + 4, this.y + 10, this.w - 8, 8);
      // lettuce
      ctx.fillStyle = '#4caf50';
      ctx.fillRect(this.x + 6, this.y + 6, this.w - 12, 4);
      // tomato
      ctx.fillStyle = '#f44336';
      ctx.beginPath();
      ctx.arc(this.x + this.w/2, this.y + 14, 8, 0, Math.PI*2);
      ctx.fill();
      // bottom bun
      ctx.fillStyle = '#deb887';
      ctx.fillRect(this.x, this.y + 18, this.w, 6);
    }
    update(mx) {
      // mouse or touch
      this.x = mx - this.w/2;
      if (this.x < 0) this.x = 0;
      if (this.x + this.w > W) this.x = W - this.w;
    }
  }

  class Ball {
    constructor() {
      this.reset();
    }
    reset() {
      this.r = 8;
      this.x = paddle ? paddle.x + paddle.w/2 : W/2;
      this.y = paddle ? paddle.y - this.r - 2 : H - 100;
      this.vx = (Math.random() < 0.5 ? -1 : 1) * 4;
      this.vy = -6;
    }
    draw() {
      ctx.fillStyle = '#fff';
      ctx.beginPath();
      ctx.arc(this.x, this.y, this.r, 0, Math.PI*2);
      ctx.fill();
      ctx.strokeStyle = '#ffd166';
      ctx.lineWidth = 2;
      ctx.stroke();
    }
    update() {
      this.x += this.vx;
      this.y += this.vy;
      // walls
      if (this.x - this.r < 0 || this.x + this.r > W) this.vx *= -1;
      if (this.y - this.r < 0) this.vy *= -1;
      // paddle
      if (this.y + this.r > paddle.y &&
          this.x > paddle.x && this.x < paddle.x + paddle.w &&
          this.vy > 0) {
        const hit = (this.x - (paddle.x + paddle.w/2)) / (paddle.w/2);
        this.vx = hit * 7;
        this.vy = -Math.abs(this.vy) - 1;
        // tiny speed ramp
        if (Math.abs(this.vx) < 1) this.vx = 1.5 * Math.sign(this.vx);
      }
      // bottom = lose life
      if (this.y - this.r > H) {
        lives--;
        if (lives <= 0) gameOver();
        else ball.reset();
      }
    }
  }

  class Brick {
    constructor(x, y, w, h, color) {
      this.x = x; this.y = y; this.w = w; this.h = h;
      this.color = color;
      this.hits = 1; // 1-hit bricks
    }
    draw() {
      ctx.fillStyle = this.color;
      ctx.fillRect(this.x, this.y, this.w, this.h);
      ctx.strokeStyle = 'rgba(0,0,0,.3)';
      ctx.strokeRect(this.x, this.y, this.w, this.h);
    }
    hit() {
      this.hits--;
      if (this.hits <= 0) {
        explode(this.x + this.w/2, this.y + this.h/2);
        score += 10;
        return true;
      }
      return false;
    }
  }

  class Heart {
    constructor(x, y) {
      this.x = x; this.y = y;
      this.vx = (Math.random() - 0.5) * 4;
      this.vy = Math.random() * -3 - 1;
      this.life = 120; // frames
      this.size = 14;
    }
    draw() {
      ctx.save();
      ctx.translate(this.x, this.y);
      ctx.fillStyle = '#ff6b9d';
      ctx.beginPath();
      ctx.moveTo(0, this.size/2);
      ctx.bezierCurveTo(this.size/2, -this.size/2, this.size, 0, 0, this.size);
      ctx.bezierCurveTo(-this.size, 0, -this.size/2, -this.size/2, 0, this.size/2);
      ctx.fill();
      ctx.restore();
    }
    update() {
      this.x += this.vx;
      this.y += this.vy;
      this.vy += 0.15; // gravity
      this.life--;
      // collect by paddle
      if (this.y + this.size/2 > paddle.y &&
          this.x > paddle.x && this.x < paddle.x + paddle.w) {
        lives = Math.min(5, lives + 1);
        score += 50;
        return false;
      }
      return this.life > 0 && this.y < H + 50;
    }
  }

  class Particle {
    constructor(x, y, color) {
      this.x = x; this.y = y;
      this.vx = (Math.random() - 0.5) * 8;
      this.vy = (Math.random() - 0.5) * 8;
      this.color = color;
      this.life = 40;
      this.size = Math.random() * 3 + 1;
    }
    draw() {
      ctx.globalAlpha = this.life / 40;
      ctx.fillStyle = this.color;
      ctx.fillRect(this.x, this.y, this.size, this.size);
      ctx.globalAlpha = 1;
    }
    update() {
      this.x += this.vx;
      this.y += this.vy;
      this.vy += 0.2;
      this.life--;
      return this.life > 0;
    }
  }

  // ---------- FUNCTIONS ----------
  function makeBricks() {
    bricks = [];
    const rows = 5;
    const cols = Math.floor(W / 70);
    const bw = (W - 40) / cols;
    const bh = 24;
    const colors = ['#ff6b9d', '#ffd166', '#06d6a0', '#118ab2', '#ef476f'];
    for (let r = 0; r < rows; r++) {
      for (let c = 0; c < cols; c++) {
        bricks.push(new Brick(
          20 + c * bw,
          60 + r * bh + 20,
          bw - 4,
          bh - 4,
          colors[r % colors.length]
        ));
      }
    }
  }

  function explode(x, y) {
    // hearts
    for (let i = 0; i < 12; i++) {
      hearts.push(new Heart(x, y));
    }
    // spark particles
    const colors = ['#ff6b9d', '#ffd166', '#fff'];
    for (let i = 0; i < 20; i++) {
      particles.push(new Particle(x, y, colors[Math.floor(Math.random()*colors.length)]));
    }
  }

  function gameOver() {
    running = false;
    overlay.querySelector('h1').textContent = 'GAME OVER 🍔';
    overlay.querySelector('p').textContent = `Score: ${score}  |  Level: ${level}`;
    startBtn.textContent = 'Play Again';
    overlay.classList.remove('hidden');
  }

  function nextLevel() {
    level++;
    score += 100 * level;
    makeBricks();
    ball.reset();
  }

  // ---------- INPUT ----------
  let mouseX = W/2;
  canvas.addEventListener('mousemove', e => {
    const rect = canvas.getBoundingClientRect();
    mouseX = (e.clientX - rect.left) * (W / rect.width);
  });
  canvas.addEventListener('touchmove', e => {
    e.preventDefault();
    const rect = canvas.getBoundingClientRect();
    const touch = e.touches[0];
    mouseX = (touch.clientX - rect.left) * (W / rect.width);
  }, { passive: false });

  document.addEventListener('keydown', e => {
    if (e.key === ' ' || e.key === 'ArrowLeft' || e.key === 'ArrowRight') {
      if (!running) startGame();
    }
    // manual arrow control fallback
    if (running && !autoPlay) {
      if (e.key === 'ArrowLeft') mouseX = Math.max(mouseX - 20, paddle.w/2);
      if (e.key === 'ArrowRight') mouseX = Math.min(mouseX + 20, W - paddle.w/2);
    }
  });

  startBtn.addEventListener('click', startGame);

  function startGame() {
    score = 0; lives = 3; level = 1;
    paddle = new Paddle();
    ball = new Ball();
    makeBricks();
    hearts = []; particles = [];
    running = true;
    overlay.classList.add('hidden');
    requestAnimationFrame(gameLoop);
  }

  // ---------- AUTO PLAY (demo mode) ----------
  function autoAIDemo() {
    if (!running) return;
    // simple AI: move paddle toward ball
    const target = ball.x;
    const paddleCenter = paddle.x + paddle.w/2;
    const diff = target - paddleCenter;
    if (Math.abs(diff) > 2) {
      mouseX += Math.sign(diff) * Math.min(Math.abs(diff), 8);
    }
  }

  // ---------- MAIN LOOP ----------
  function gameLoop(ts) {
    if (!running) return;
    const dt = ts - lastTime;
    lastTime = ts;

    // auto-play
    if (autoPlay) autoAIDemo();

    paddle.update(mouseX);
    ball.update();

    // bricks
    for (let i = bricks.length - 1; i >= 0; i--) {
      const b = bricks[i];
      if (ball.y - ball.r < b.y + b.h &&
          ball.y + ball.r > b.y &&
          ball.x + ball.r > b.x &&
          ball.x - ball.r < b.x + b.w) {
        // collision
        const hit = b.hit();
        if (hit) bricks.splice(i, 1);
        // bounce
        const prevVx = ball.vx;
        ball.vy *= -1;
        // add slight horizontal based on where it hit
        const hitPos = (ball.x - (b.x + b.w/2)) / (b.w/2);
        ball.vx = hitPos * 5 + prevVx * 0.3;
      }
    }

    // hearts
    for (let i = hearts.length - 1; i >= 0; i--) {
      if (!hearts[i].update()) hearts.splice(i, 1);
    }

    // particles
    for (let i = particles.length - 1; i >= 0; i--) {
      if (!particles[i].update()) particles.splice(i, 1);
    }

    // level complete
    if (bricks.length === 0) {
      nextLevel();
    }

    draw();
    requestAnimationFrame(gameLoop);
  }

  function draw() {
    // background gradient
    const grad = ctx.createLinearGradient(0, 0, 0, H);
    grad.addColorStop(0, '#16213e');
    grad.addColorStop(1, '#0f3460');
    ctx.fillStyle = grad;
    ctx.fillRect(0, 0, W, H);

    // grid lines
    ctx.strokeStyle = 'rgba(255,255,255,0.05)';
    ctx.lineWidth = 1;
    for (let x = 0; x < W; x += 40) {
      ctx.beginPath(); ctx.moveTo(x, 0); ctx.lineTo(x, H); ctx.stroke();
    }
    for (let y = 0; y < H; y += 40) {
      ctx.beginPath(); ctx.moveTo(0, y); ctx.lineTo(W, y); ctx.stroke();
    }

    // draw game objects
    bricks.forEach(b => b.draw());
    hearts.forEach(h => h.draw());
    particles.forEach(p => p.draw());
    paddle.draw();
    ball.draw();

    // HUD
    ctx.fillStyle = '#fff';
    ctx.font = 'bold 18px Arial';
    ctx.textAlign = 'left';
    ctx.fillText(`Score: ${score}`, 16, 30);
    ctx.fillText(`Lives: ${'❤️'.repeat(lives)}`, 16, 55);
    ctx.fillText(`Level: ${level}`, W - 120, 30);
    ctx.textAlign = 'right';
  }

  // ---------- INIT ----------
  // show overlay until user clicks
  overlay.classList.remove('hidden');
})();
</script>
</body>
</html>