Models 44

Nemotron 3.5 Super VL (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
32.3 s
Cost
$0
Output tokens
4,816
Spent thinking
0 tokens
Speed
151.4 tok/s
Console errors
1
First token after
481 ms
First visible text after
481 ms
Prompt tokens
531
Code size
20.6 KB
Finish reason
stop
Served by
Nvidia
Model id
nvidia/nemotron-3.5-super-vl: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.

Cannot read properties of undefined (reading 'draw')

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 · 652 lines

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Neon Breakout</title>
    <style>
        :root {
            --bg: #05050a;
            --panel: #111320;
            --text: #e8eaf6;
            --accent: #00f2ff;
            --danger: #ff4d6d;
            --success: #00ff88;
            --warn: #ffd700;
        }

        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
            font-family: 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
        }

        body {
            background-color: var(--bg);
            color: var(--text);
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            min-height: 100vh;
            overflow: hidden;
        }

        #game-container {
            position: relative;
            width: 100%;
            max-width: 700px;
            height: 800px;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            padding: 20px;
            box-shadow: 0 0 50px rgba(0, 242, 255, 0.1);
        }

        canvas {
            background-color: var(--panel);
            border-radius: 8px;
            border: 2px solid #22253a;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
            display: block;
        }

        #hud {
            position: absolute;
            top: 10px;
            left: 0;
            width: 100%;
            display: flex;
            justify-content: space-between;
            font-size: 18px;
            font-weight: bold;
            pointer-events: none;
            padding: 0 20px;
        }

        .hud-item {
            background: rgba(0, 0, 0, 0.5);
            padding: 5px 15px;
            border-radius: 4px;
            border: 1px solid #333;
        }

        #overlay {
            position: absolute;
            inset: 0;
            background: rgba(5, 5, 10, 0.85);
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            text-align: center;
            z-index: 10;
            transition: opacity 0.3s;
        }

        h1 {
            font-size: 48px;
            margin-bottom: 10px;
            text-transform: uppercase;
            letter-spacing: 4px;
            color: var(--accent);
            text-shadow: 0 0 15px rgba(0, 242, 255, 0.5);
        }

        .btn {
            margin-top: 20px;
            padding: 12px 30px;
            font-size: 18px;
            background: transparent;
            color: var(--text);
            border: 2px solid var(--accent);
            cursor: pointer;
            border-radius: 5px;
            transition: all 0.2s;
        }

        .btn:hover {
            background: var(--accent);
            color: var(--bg);
            box-shadow: 0 0 20px rgba(0, 242, 255, 0.6);
        }

        .controls-hint {
            margin-top: 10px;
            font-size: 14px;
            color: #888;
        }

        .powerup-display {
            margin-top: 10px;
            font-size: 14px;
            color: var(--warn);
            display: none;
        }
        
        .powerup-display.active {
            display: block;
            animation: pulse 1s infinite;
        }

        @keyframes pulse {
            0%, 100% { opacity: 1; }
            50% { opacity: 0.5; }
        }
    </style>
</head>
<body>

    <div id="game-container">
        <div id="hud">
            <div class="hud-item">Score: <span id="score">0</span></div>
            <div class="hud-item">Lives: <span id="lives">3</span></div>
        </div>

        <canvas id="gameCanvas"></canvas>

        <div id="overlay">
            <h1>Neon Breakout</h1>
            <p id="overlay-text">Click or press a key to start</p>
            <button class="btn" id="start-btn">Start Game</button>
            <div class="controls-hint">Mouse or Arrow Keys to Move Paddle</div>
            <div class="powerup-display" id="powerup-text"></div>
        </div>
    </div>

    <script>
        const canvas = document.getElementById('gameCanvas');
        const ctx = canvas.getContext('2d');
        const scoreEl = document.getElementById('score');
        const livesEl = document.getElementById('lives');
        const overlay = document.getElementById('overlay');
        const overlayText = document.getElementById('overlay-text');
        const startBtn = document.getElementById('start-btn');
        const powerupDisplay = document.getElementById('powerup-text');

        // Game Configuration
        const CONFIG = {
            width: 700,
            height: 800,
            paddleWidth: 100,
            paddleHeight: 15,
            paddleSpeed: 7,
            ballRadius: 8,
            ballSpeed: 5,
            brickRows: 7,
            brickCols: 10,
            brickPadding: 5,
            brickOffsetTop: 40,
            brickOffsetLeft: 30,
            brickWidth: 55,
            brickHeight: 20,
            colors: {
                normal: '#00f2ff',
                tough: '#ff4d6d',
                powerup: '#ffd700',
                paddle: '#e8eaf6',
                bg: '#111320'
            }
        };

        canvas.width = CONFIG.width;
        canvas.height = CONFIG.height;

        // State
        let score = 0;
        let lives = 3;
        let gameRunning = false;
        let gameOver = false;
        let victory = false;
        let animationId;

        // Input
        const keys = {};
        let mouseX = 0;

        window.addEventListener('keydown', e => {
            keys[e.code] = true;
            if (!gameRunning && (e.code === 'Space' || e.code === 'Enter')) startGame();
        });
        window.addEventListener('keyup', e => keys[e.code] = false);

        window.addEventListener('mousemove', e => {
            const rect = canvas.getBoundingClientRect();
            mouseX = e.clientX - rect.left;
        });

        startBtn.addEventListener('click', startGame);

        // Classes
        class Ball {
            constructor(x, y) {
                this.x = x;
                this.y = y;
                this.dx = (Math.random() > 0.5 ? 1 : -1) * CONFIG.ballSpeed;
                this.dy = -CONFIG.ballSpeed;
                this.radius = CONFIG.ballRadius;
                this.color = CONFIG.colors.normal;
            }

            draw() {
                ctx.beginPath();
                ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
                ctx.fillStyle = this.color;
                ctx.fill();
                ctx.closePath();
            }

            update() {
                this.x += this.dx;
                this.y += this.dy;

                // Wall collisions
                if (this.x + this.radius > CONFIG.width || this.x - this.radius < 0) {
                    this.dx *= -1;
                    this.x = Math.max(this.radius, Math.min(this.x, CONFIG.width - this.radius));
                }
                if (this.y - this.radius < 0) {
                    this.dy *= -1;
                    this.y = this.radius;
                }
                if (this.y + this.radius > CONFIG.height) {
                    return 'dead';
                }
                return 'alive';
            }
        }

        class Paddle {
            constructor() {
                this.width = CONFIG.paddleWidth;
                this.height = CONFIG.paddleHeight;
                this.x = (CONFIG.width - this.width) / 2;
                this.y = CONFIG.height - 40;
                this.speed = CONFIG.paddleSpeed;
            }

            draw() {
                ctx.fillStyle = CONFIG.colors.paddle;
                ctx.shadowColor = CONFIG.colors.accent;
                ctx.shadowBlur = 10;
                ctx.fillRect(this.x, this.y, this.width, this.height);
                ctx.shadowBlur = 0;
            }

            update() {
                if (keys['ArrowLeft'] || keys['KeyA']) this.x -= this.speed;
                if (keys['ArrowRight'] || keys['KeyD']) this.x += this.speed;

                // Mouse control
                if (mouseX !== 0) {
                    this.x = mouseX - this.width / 2;
                }

                // Boundaries
                if (this.x < 0) this.x = 0;
                if (this.x + this.width > CONFIG.width) this.x = CONFIG.width - this.width;
            }

            widen() {
                this.width = 150;
                setTimeout(() => {
                    this.width = CONFIG.paddleWidth;
                    // clamp position if needed
                    if (this.x + this.width > CONFIG.width) this.x = CONFIG.width - this.width;
                }, 10000);
            }
        }

        class Brick {
            constructor(x, y, type, hasPowerup = false) {
                this.x = x;
                this.y = y;
                this.width = CONFIG.brickWidth;
                this.height = CONFIG.brickHeight;
                this.type = type; // 'normal', 'tough'
                this.hits = type === 'tough' ? 2 : 1;
                this.hasPowerup = hasPowerup;
                this.powerupType = Math.random() > 0.5 ? 'wide' : 'multiball';
                this.active = true;
                this.cracked = false;
            }

            draw() {
                if (!this.active) return;

                ctx.fillStyle = this.type === 'tough' ? CONFIG.colors.tough : CONFIG.colors.normal;
                if (this.cracked) ctx.globalAlpha = 0.6;

                // Draw brick
                ctx.beginPath();
                ctx.roundRect(this.x, this.y, this.width, this.height, 3);
                ctx.fill();
                ctx.globalAlpha = 1;

                // Powerup icon
                if (this.hasPowerup) {
                    ctx.fillStyle = CONFIG.colors.powerup;
                    ctx.font = '12px Arial';
                    ctx.textAlign = 'center';
                    ctx.textBaseline = 'middle';
                    ctx.fillText(this.powerupType === 'wide' ? 'W' : 'M', 
                        this.x + this.width / 2, this.y + this.height / 2);
                }
            }

            hit() {
                this.hits--;
                if (this.hits === 1 && this.type === 'tough') this.cracked = true;
                if (this.hits <= 0) {
                    this.active = false;
                    createParticles(this.x + this.width/2, this.y + this.height/2, 
                        this.type === 'tough' ? CONFIG.colors.tough : CONFIG.colors.normal);
                    if (this.hasPowerup) {
                        powerups.push(new Powerup(this.x + this.width/2, this.y + this.height/2, this.powerupType));
                    }
                    return true;
                }
                return false;
            }
        }

        class Powerup {
            constructor(x, y, type) {
                this.x = x;
                this.y = y;
                this.radius = 6;
                this.type = type; // 'wide' or 'multiball'
                this.speed = 3;
                this.active = true;
                this.color = CONFIG.colors.powerup;
            }

            draw() {
                if (!this.active) return;
                ctx.fillStyle = this.color;
                ctx.beginPath();
                ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
                ctx.fill();
                ctx.closePath();
                
                // Icon
                ctx.fillStyle = '#000';
                ctx.font = '10px Arial';
                ctx.textAlign = 'center';
                ctx.textBaseline = 'middle';
                ctx.fillText(this.type === 'wide' ? 'W' : 'M', this.x, this.y);
            }

            update() {
                this.y += this.speed;
                if (this.y > CONFIG.height) this.active = false;
            }
        }

        class Particle {
            constructor(x, y, color) {
                this.x = x;
                this.y = y;
                this.color = color;
                this.size = Math.random() * 3 + 1;
                this.speedX = Math.random() * 3 - 1.5;
                this.speedY = Math.random() * 3 - 1.5;
                this.life = 1.0;
                this.decay = Math.random() * 0.03 + 0.02;
            }

            draw() {
                ctx.globalAlpha = this.life;
                ctx.fillStyle = this.color;
                ctx.fillRect(this.x, this.y, this.size, this.size);
                ctx.globalAlpha = 1;
            }

            update() {
                this.x += this.speedX;
                this.y += this.speedY;
                this.life -= this.decay;
            }
        }

        // Game Objects
        let paddle;
        let balls = [];
        let bricks = [];
        let powerups = [];
        let particles = [];

        function initBricks() {
            bricks = [];
            for (let r = 0; r < CONFIG.brickRows; r++) {
                for (let c = 0; c < CONFIG.brickCols; c++) {
                    const brickX = c * (CONFIG.brickWidth + CONFIG.brickPadding) + CONFIG.brickOffsetLeft;
                    const brickY = r * (CONFIG.brickHeight + CONFIG.brickPadding) + CONFIG.brickOffsetTop;
                    
                    let type = 'normal';
                    if (r < 2) type = 'tough';
                    
                    let hasPowerup = false;
                    // Some bricks carry powerups
                    if (r % 3 === 0 && c % 4 === 0) hasPowerup = true;

                    bricks.push(new Brick(brickX, brickY, type, hasPowerup));
                }
            }
        }

        function startGame() {
            score = 0;
            lives = 3;
            gameRunning = true;
            gameOver = false;
            victory = false;
            updateHUD();
            overlay.style.display = 'none';
            powerupDisplay.classList.remove('active');
            
            paddle = new Paddle();
            balls = [new Ball(CONFIG.width / 2, CONFIG.height - 50)];
            powerups = [];
            particles = [];
            initBricks();
            
            if (animationId) cancelAnimationFrame(animationId);
            gameLoop();
        }

        function endGame(win) {
            gameRunning = false;
            gameOver = !win;
            victory = win;
            overlay.style.display = 'flex';
            overlayText.textContent = win ? "VICTORY!" : "GAME OVER";
            startBtn.textContent = "Play Again";
            startBtn.style.display = 'block';
        }

        function updateHUD() {
            scoreEl.textContent = score;
            livesEl.textContent = lives;
        }

        function createParticles(x, y, color) {
            for (let i = 0; i < 10; i++) {
                particles.push(new Particle(x, y, color));
            }
        }

        function resolveBallPaddleCollision(ball, paddle) {
            // Check if ball hits paddle
            if (ball.y + ball.radius > paddle.y && 
                ball.y - ball.radius < paddle.y + paddle.height &&
                ball.x > paddle.x && 
                ball.x < paddle.x + paddle.width) {
                
                // Calculate hit position (-1 to 1)
                const collidePoint = (ball.x - (paddle.x + paddle.width / 2)) / (paddle.width / 2);
                
                // Angle calculation
                const angle = collidePoint * (Math.PI / 3); // Max 60 degrees
                
                // Set velocity
                const speed = Math.sqrt(ball.dx * ball.dx + ball.dy * ball.dy);
                ball.dx = speed * Math.sin(angle);
                ball.dy = -speed * Math.cos(angle);
                
                // Push ball out of paddle to prevent sticking
                ball.y = paddle.y - ball.radius;
                
                return true;
            }
            return false;
        }

        function checkCollisions() {
            // Bricks
            for (let i = bricks.length - 1; i >= 0; i--) {
                const brick = bricks[i];
                if (!brick.active) continue;

                for (let b = 0; b < balls.length; b++) {
                    const ball = balls[b];
                    
                    // Simple AABB collision
                    if (ball.x > brick.x && ball.x < brick.x + brick.width &&
                        ball.y > brick.y && ball.y < brick.y + brick.height) {
                        
                        const broken = brick.hit();
                        if (broken) {
                            score += brick.type === 'tough' ? 20 : 10;
                            updateHUD();
                            
                            // Bounce direction based on hit side
                            const prevX = ball.x - ball.dx;
                            const prevY = ball.y - ball.dy;
                            
                            // Determine side hit
                            const top = prevY <= brick.y;
                            const bottom = prevY >= brick.y + brick.height;
                            const left = prevX <= brick.x;
                            const right = prevX >= brick.x + brick.width;

                            if (top || bottom) ball.dy *= -1;
                            if (left || right) ball.dx *= -1;
                        }
                    }
                }
            }

            // Paddle collisions
            for (let ball of balls) {
                resolveBallPaddleCollision(ball, paddle);
            }

            // Powerups
            for (let i = powerups.length - 1; i >= 0; i--) {
                const p = powerups[i];
                p.update();
                
                // Paddle collision
                if (p.x > paddle.x && p.x < paddle.x + paddle.width &&
                    p.y + p.radius > paddle.y && p.y < paddle.y + paddle.height) {
                    
                    activatePowerup(p.type);
                    p.active = false;
                }
            }

            // Remove inactive
            bricks = bricks.filter(b => b.active);
            powerups = powerups.filter(p => p.active);
            particles = particles.filter(p => p.life > 0);

            // Check victory
            if (bricks.length === 0) {
                endGame(true);
            }
        }

        function activatePowerup(type) {
            if (type === 'wide') {
                paddle.widen();
                showPowerupText('Paddle WIDE!');
            } else if (type === 'multiball') {
                const currentBalls = balls.length;
                for (let i = 0; i < 3; i++) {
                    balls.push(new Ball(paddle.x + paddle.width / 2, paddle.y - 20));
                }
                showPowerupText('MULTI-BALL!');
            }
        }

        function showPowerupText(text) {
            powerupDisplay.textContent = text;
            powerupDisplay.classList.add('active');
            setTimeout(() => powerupDisplay.classList.remove('active'), 3000);
        }

        function draw() {
            // Clear
            ctx.fillStyle = CONFIG.colors.bg;
            ctx.fillRect(0, 0, CONFIG.width, CONFIG.height);

            // Draw game objects
            paddle.draw();
            
            for (let ball of balls) ball.draw();
            for (let brick of bricks) brick.draw();
            for (let p of powerups) p.draw();
            for (let p of particles) {
                p.update();
                p.draw();
            }
        }

        function update() {
            if (!gameRunning) return;

            paddle.update();

            // Update balls
            for (let i = balls.length - 1; i >= 0; i--) {
                const status = balls[i].update();
                if (status === 'dead') {
                    balls.splice(i, 1);
                }
            }

            // If no balls left, lose life
            if (balls.length === 0) {
                lives--;
                updateHUD();
                if (lives <= 0) {
                    endGame(false);
                } else {
                    // Reset paddle and ball
                    paddle = new Paddle();
                    balls = [new Ball(CONFIG.width / 2, CONFIG.height - 50)];
                    // Brief pause
                    setTimeout(() => {}, 500);
                }
            }

            checkCollisions();
        }

        function gameLoop() {
            update();
            draw();
            if (gameRunning) {
                animationId = requestAnimationFrame(gameLoop);
            }
        }

        // Initial draw
        draw();
    </script>
</body>
</html>