Models 44

Gemini 3.1 Flash Lite

by GoogleReasoningClean
Open in new window

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

How it went

Total time
10.6 s
Cost
$0.0056
Output tokens
3,675
Spent thinking
1,732 tokens
Speed
378.9 tok/s
Console errors
0
First token after
937 ms
First visible text after
6.3 s
Prompt tokens
448
Code size
6.4 KB
Finish reason
stop
Served by
Google
Model id
google/gemini-3.1-flash-lite
Reasoning sent
{"effort":"high"}
Max output
65,536 tokens
Generated
Nov 12, 2026

What it was asked

The prompt
“a 3D aquarium with Three.js where the fish swim away when I move the mouse near them (Load Three.js only through this import map: <script type="importmap">{"imports":{"three":"https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js","three/addons/":"https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/"}}</script>)”
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 · 168 lines

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>3D Aquarium Demo</title>
    <style>
        body, html { margin: 0; padding: 0; width: 100%; height: 100%; overflow: hidden; background: #001; font-family: sans-serif; }
        canvas { display: block; }
        #overlay {
            position: absolute; top: 0; left: 0; width: 100%; height: 100%;
            display: flex; flex-direction: column; justify-content: center; align-items: center;
            background: rgba(0,0,0,0.5); color: white; cursor: pointer; z-index: 10;
        }
    </style>
    <script type="importmap">
        {
            "imports": {
                "three": "https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js",
                "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/"
            }
        }
    </script>
</head>
<body>

    <div id="overlay">
        <h1>3D Aquarium</h1>
        <p>Click or press any key to start</p>
    </div>

    <script type="module">
        import * as THREE from 'three';

        // --- Setup ---
        const scene = new THREE.Scene();
        scene.fog = new THREE.FogExp2(0x002244, 0.15);
        const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
        const renderer = new THREE.WebGLRenderer({ antialias: true });
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.setClearColor(0x001122);
        document.body.appendChild(renderer.domElement);

        const light = new THREE.PointLight(0xffffff, 100, 20);
        light.position.set(0, 5, 5);
        scene.add(light);
        scene.add(new THREE.AmbientLight(0x4488ff, 2));

        // --- Aquarium Bounds ---
        const boxGeo = new THREE.BoxGeometry(10, 6, 10);
        const boxMat = new THREE.MeshBasicMaterial({ color: 0x004466, transparent: true, opacity: 0.1, side: THREE.BackSide });
        const tank = new THREE.Mesh(boxGeo, boxMat);
        scene.add(tank);

        camera.position.z = 8;
        camera.position.y = 2;
        camera.lookAt(0, 0, 0);

        // --- Fish Class ---
        class Fish {
            constructor() {
                this.group = new THREE.Group();
                
                // Body
                const bodyGeo = new THREE.ConeGeometry(0.2, 0.6, 8);
                const bodyMat = new THREE.MeshPhongMaterial({ color: 0xffaa00 });
                this.body = new THREE.Mesh(bodyGeo, bodyMat);
                this.body.rotation.x = Math.PI / 2;
                this.group.add(this.body);

                // Tail
                const tailGeo = new THREE.PlaneGeometry(0.3, 0.3);
                const tailMat = new THREE.MeshPhongMaterial({ color: 0xffaa00, side: THREE.DoubleSide });
                this.tail = new THREE.Mesh(tailGeo, tailMat);
                this.tail.position.z = -0.4;
                this.group.add(this.tail);

                this.velocity = new THREE.Vector3(Math.random() - 0.5, Math.random() - 0.5, Math.random() - 0.5).normalize().multiplyScalar(0.05);
                this.group.position.set((Math.random() - 0.5) * 8, (Math.random() - 0.5) * 4, (Math.random() - 0.5) * 8);
                this.group.lookAt(this.group.position.clone().add(this.velocity));
                
                scene.add(this.group);
            }

            update(mousePos, scare) {
                // Random wander
                this.velocity.add(new THREE.Vector3(Math.random()-0.5, Math.random()-0.5, Math.random()-0.5).multiplyScalar(0.005));
                
                // Avoid mouse
                if (scare) {
                    const dir = this.group.position.clone().sub(mousePos);
                    const dist = dir.length();
                    if (dist < 2.5) {
                        dir.normalize().multiplyScalar(0.1);
                        this.velocity.add(dir);
                    }
                }

                // Speed limit
                if (this.velocity.length() > 0.1) this.velocity.normalize().multiplyScalar(0.1);

                this.group.position.add(this.velocity);
                
                // Boundaries
                if (Math.abs(this.group.position.x) > 4.5) this.velocity.x *= -1;
                if (Math.abs(this.group.position.y) > 2.5) this.velocity.y *= -1;
                if (Math.abs(this.group.position.z) > 4.5) this.velocity.z *= -1;

                this.group.lookAt(this.group.position.clone().add(this.velocity));

                // Wiggle
                this.tail.rotation.y = Math.sin(Date.now() * 0.02) * 0.5;
            }
        }

        const fishes = Array.from({ length: 15 }, () => new Fish());

        // --- Interaction ---
        let mouse = new THREE.Vector3(0, 0, 0);
        let raycaster = new THREE.Raycaster();
        let mouseNDC = new THREE.Vector2(0, 0);
        let started = false;

        function updateMouse(x, y) {
            mouseNDC.x = (x / window.innerWidth) * 2 - 1;
            mouseNDC.y = -(y / window.innerHeight) * 2 + 1;
            raycaster.setFromCamera(mouseNDC, camera);
            // Project onto Z=0 plane
            const planeZ = new THREE.Plane(new THREE.Vector3(0, 0, 1), 0);
            raycaster.ray.intersectPlane(planeZ, mouse);
        }

        window.addEventListener('mousemove', (e) => updateMouse(e.clientX, e.clientY));
        window.addEventListener('keydown', () => { if (!started) start(); });
        window.addEventListener('mousedown', () => { if (!started) start(); });

        function start() {
            started = true;
            document.getElementById('overlay').style.display = 'none';
        }

        // --- Animation Loop ---
        let time = 0;
        function animate() {
            requestAnimationFrame(animate);

            time += 0.01;
            if (!started) {
                // Auto move mouse for demo
                const mX = Math.sin(time) * 4;
                const mY = Math.cos(time * 0.7) * 2;
                mouse.set(mX, mY, 0);
            }

            fishes.forEach(f => f.update(mouse, true));
            renderer.render(scene, camera);
        }

        window.addEventListener('resize', () => {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
        });

        animate();
    </script>
</body>
</html>
Reasoning trace (1,732 tokens)
**Developing Aquarium Behavior**

I'm currently focused on implementing the fish's evasive maneuver. The goal is to have them react dynamically to the mouse's proximity, using the provided Three.js CDN within a single, self-contained file.

**Refining Fish Movement**

I'm currently integrating the repulsion logic, focusing on how fish react when the cursor is within their perceived danger zone. My aim is to ensure their evasive maneuvers feel natural and responsive within the aquarium's boundaries.

**Implementing Mouse Repulsion**

I'm now working on the core logic for the fish to swim away from the cursor. This involves converting the mouse's 2D position into a 3D vector and calculating a repulsion force to keep them within bounds.

**Adapting Repulsion Logic**

I'm exploring alternatives to raycasting for repulsion, considering simpler 3D projection or direct position comparison to maintain performance. I'm also planning a self-playing mode with a simulated mouse.

**Constructing Fish Models**

My focus has shifted to building simple fish geometries directly within Three.js using `Group` and `Mesh`, as external models are proving complex. I'm also ensuring the fish stay within the defined aquarium boundaries.

**Initializing Aquarium Environment**

I've begun setting up the core Three.js components: the scene, camera, and renderer. My next step is to define the boundaries of the aquarium itself.

**Animating Fish Motion**

I'm now fine-tuning the fish's evasive reactions, ensuring their tail movements contribute to a more natural swimming simulation when the cursor approaches. The goal is a fluid, believable escape.

**Adding Aquarium Decor**

I'm now focusing on enhancing the aquarium's visual appeal by adding decorative elements like rocks. My aim is to create a more immersive 3D environment beyond just a simple water box, while also refining the fish's evasive behaviors.