← Canyon Run results

Canyon Run

Gemma 4 31b it · basic

Initial view of Canyon Run

Browser check: External resource unavailable. This is a technical check, not a quality review.

Reviews & generation details

Reviews

Human review · Jul 17, 2026 · rubric 1

Historical path-based review. Association with these exact bytes is unverified.

The reviewer marked this result as broken. It remains in the archive.

Visual design
Unscored
UX / feel
Unscored
Works
Unscored
Prompt spirit
Unscored
Delight
Unscored

Generation context

Imported historical artifact. Its exact original instructions and lineage are not known.

Generation prompt · exact text unavailable

See the current prompt for reference. It may differ from the instructions used to generate this artifact.

Inspect original source 17,749 bytes · SHA-256 6ab370a3266a
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>NEON CANYON RACER</title>
    <style>
        body { margin: 0; overflow: hidden; background: #050505; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; color: #fff; user-select: none; }
        #ui { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; display: flex; flex-direction: column; justify-content: space-between; padding: 30px; box-sizing: border-box; }
        #hud-top { display: flex; justify-content: space-between; align-items: flex-start; }
        #score-container { text-align: left; }
        #score { font-size: 48px; font-weight: 900; font-variant-numeric: tabular-nums; color: #ffcc00; text-shadow: 0 0 20px rgba(255, 204, 0, 0.6); }
        #multiplier { font-size: 24px; color: #ff00ff; font-weight: bold; opacity: 0; transition: opacity 0.2s, transform 0.1s; }
        #energy-container { width: 300px; height: 12px; background: rgba(255,255,255,0.1); border: 1px solid rgba(255,255,255,0.3); position: relative; overflow: hidden; border-radius: 6px; }
        #energy-bar { height: 100%; width: 100%; background: linear-gradient(90deg, #ff00cc, #33ffcc); transition: width 0.1s linear; box-shadow: 0 0 15px #33ffcc; }
        #speed-container { position: absolute; bottom: 40px; left: 50%; transform: translateX(-50%); text-align: center; }
        #speed-val { font-size: 20px; font-weight: 300; letter-spacing: 2px; opacity: 0.8; }
        #overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.8); display: flex; flex-direction: column; justify-content: center; align-items: center; pointer-events: all; z-index: 10; }
        h1 { font-size: 64px; margin: 0; letter-spacing: 10px; color: #ffcc00; text-shadow: 0 0 30px #ffcc00; }
        .btn { padding: 15px 40px; font-size: 20px; background: transparent; color: #fff; border: 2px solid #fff; cursor: pointer; margin-top: 30px; transition: all 0.3s; text-transform: uppercase; letter-spacing: 2px; }
        .btn:hover { background: #fff; color: #000; }
        #game-over-stats { text-align: center; margin-bottom: 20px; display: none; }
        .stat-line { font-size: 24px; margin: 10px 0; opacity: 0.8; }
    </style>
</head>
<body>

    <div id="ui">
        <div id="hud-top">
            <div id="score-container">
                <div id="score">0</div>
                <div id="multiplier">x1 NEAR MISS!</div>
            </div>
            <div id="energy-container">
                <div id="energy-bar"></div>
            </div>
        </div>
        <div id="speed-container">
            <div id="speed-val">SPEED: 0 KM/H</div>
        </div>
    </div>

    <div id="overlay">
        <div id="game-over-stats">
            <div class="stat-line" id="final-score">SCORE: 0</div>
            <div class="stat-line" id="final-speed">MAX SPEED: 0</div>
        </div>
        <h1 id="title">NEON CANYON</h1>
        <button class="btn" id="start-btn">Launch</button>
    </div>

    <script type="importmap">
        {
            "imports": {
                "three": "https://unpkg.com/three@0.160.0/build three.module.js",
                "three/addons/": "https://unpkg.com/three@0.160.0/examples/jsm/"
            }
        }
    </script>

    <script type="module">
        import * as THREE from 'https://unpkg.com/three@0.160.0/build/three.module.js';
        import { EffectComposer } from 'https://unpkg.com/three@0.160.0/examples/jsm/postprocessing/EffectComposer.js';
        import { RenderPass } from 'https://unpkg.com/three@0.160.0/examples/jsm/postprocessing/RenderPass.js';
        import { UnrealBloomPass } from 'https://unpkg.com/three@0.160.0/examples/jsm/postprocessing/UnrealBloomPass.js';

        // Game Constants
        const SETTINGS = {
            CHUNK_SIZE: 200,
            CHUNK_COUNT: 5,
            START_SPEED: 0.8,
            MAX_SPEED: 2.5,
            ACCEL: 0.0001,
            ENERGY_DECAY: 0.12,
            ENERGY_GAIN: 25,
            SENSITIVITY: 0.05,
            BANK_SPEED: 0.1
        };

        // Game State
        let state = {
            running: false,
            score: 0,
            energy: 100,
            speed: SETTINGS.START_SPEED,
            multiplier: 1,
            lastNearMiss: 0,
            maxSpeedReached: 0,
            playerPos: new THREE.Vector3(0, 0, 0),
            playerRot: new THREE.Euler(0, 0, 0),
            input: { x: 0, y: 0 }
        };

        // Audio Context
        let audioCtx, engineOsc, gainNode;
        function initAudio() {
            audioCtx = new (window.AudioContext || window.webkitAudioContext)();
            engineOsc = audioCtx.createOscillator();
            gainNode = audioCtx.createGain();
            engineOsc.type = 'sawtooth';
            engineOsc.frequency.setValueAtTime(50, audioCtx.currentTime);
            gainNode.gain.setValueAtTime(0.1, audioCtx.currentTime);
            engineOsc.connect(gainNode).connect(audioCtx.destination);
            engineOsc.start();
        }

        function playSound(freq, type, duration, vol = 0.1) {
            if(!audioCtx) return;
            const osc = audioCtx.createOscillator();
            const g = audioCtx.createGain();
            osc.type = type;
            osc.frequency.setValueAtTime(freq, audioCtx.currentTime);
            g.gain.setValueAtTime(vol, audioCtx.currentTime);
            g.gain.exponentialRampToValueAtTime(0.0001, audioCtx.currentTime + duration);
            osc.connect(g).connect(audioCtx.destination);
            osc.start();
            osc.stop(audioCtx.currentTime + duration);
        }

        // Three.js Core
        const scene = new THREE.Scene();
        scene.background = new THREE.Color(0x0a0a1a);
        scene.fog = new THREE.FogExp2(0x0a0a1a, 0.005);

        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.setPixelRatio(window.devicePixelRatio);
        renderer.shadowMap.enabled = true;
        document.body.appendChild(renderer.domElement);

        // Post Processing
        const renderScene = new RenderPass(scene, camera);
        const bloomPass = new UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight), 1.5, 0.4, 0.85);
        bloomPass.threshold = 0.2;
        bloomPass.strength = 1.2;
        const composer = new EffectComposer(renderer);
        composer.addPass(renderScene);
        composer.addPass(bloomPass);

        // Lighting
        const sun = new THREE.DirectionalLight(0xffaa00, 2);
        sun.position.set(10, 20, 10);
        sun.castShadow = true;
        scene.add(sun);
        scene.add(new THREE.AmbientLight(0x404080, 0.5));

        // Player Craft
        const craftGroup = new THREE.Group();
        const craftBody = new THREE.Mesh(
            new THREE.ConeGeometry(0.2, 1, 4),
            new THREE.MeshPhongMaterial({ color: 0xcccccc, flatShading: true })
        );
        craftBody.rotation.x = Math.PI / 2;
        craftGroup.add(craftBody);

        const engineGlow = new THREE.Mesh(
            new THREE.SphereGeometry(0.15, 8, 8),
            new THREE.MeshBasicMaterial({ color: 0x00ffff })
        );
        engineGlow.position.z = 0.5;
        craftGroup.add(engineGlow);

        scene.add(craftGroup);

        // Procedural Generation
        const chunks = [];
        const obstacles = [];
        const collectibles = [];
        const chunkGeometry = new THREE.BoxGeometry(1, 1, 1);
        const wallMaterial = new THREE.MeshPhongMaterial({ color: 0x332244, flatShading: true });
        const orbMaterial = new THREE.MeshBasicMaterial({ color: 0x00ffff });

        function createChunk(zOffset) {
            const chunk = new THREE.Group();
            const centerX = (Math.random() - 0.5) * 20;
            const centerZ = zOffset;

            // Floor
            const floor = new THREE.Mesh(
                new THREE.PlaneGeometry(40, SETTINGS.CHUNK_SIZE),
                wallMaterial
            );
            floor.rotation.x = -Math.PI / 2;
            floor.position.set(centerX, -2, centerZ);
            floor.receiveShadow = true;
            chunk.add(floor);

            // Walls
            for(let i=0; i<8; i++) {
                const w = new THREE.Mesh(
                    new THREE.BoxGeometry(2 + Math.random()*5, 10 + Math.random()*20, 10 + Math.random()*20),
                    wallMaterial
                );
                const side = Math.random() > 0.5 ? 1 : -1;
                w.position.set(centerX + (side * (8 + Math.random()*10)), 0, centerZ + (Math.random()-0.5)*SETTINGS.CHUNK_SIZE);
                w.castShadow = true;
                w.receiveShadow = true;
                chunk.add(w);
                obstacles.push(w);
            }

            // Collectibles
            for(let i=0; i<3; i++) {
                const orb = new THREE.Mesh(new THREE.SphereGeometry(0.5, 8, 8), orbMaterial);
                orb.position.set(centerX + (Math.random()-0.5)*15, Math.random()*5, centerZ + (Math.random()-0.5)*SETTINGS.CHUNK_SIZE);
                chunk.add(orb);
                collectibles.push(orb);
            }

            scene.add(chunk);
            chunks.push({ group: chunk, z: centerZ });
        }

        // Init Chunks
        for(let i=0; i<SETTINGS.CHUNK_COUNT; i++) {
            createChunk(-i * SETTINGS.CHUNK_SIZE);
        }

        // Input handling
        window.addEventListener('keydown', (e) => {
            if(e.key === 'ArrowLeft' || e.key === 'a') state.input.x = -1;
            if(e.key === 'ArrowRight' || e.key === 'd') state.input.x = 1;
            if(e.key === 'ArrowUp' || e.key === 'w') state.input.y = 1;
            if(e.key === 'ArrowDown' || e.key === 's') state.input.y = -1;
        });
        window.addEventListener('keyup', (e) => {
            if(['ArrowLeft', 'ArrowRight', 'a', 'd'].includes(e.key)) state.input.x = 0;
            if(['ArrowUp', 'ArrowDown', 'w', 's'].includes(e.key)) state.input.y = 0;
        });
        // Touch support
        window.addEventListener('touchstart', (e) => {
            const touchX = e.touches[0].clientX / window.innerWidth;
            const touchY = e.touches[0].clientY / window.innerHeight;
            state.input.x = touchX < 0.3 ? -1 : (touchX > 0.7 ? 1 : 0);
            state.input.y = touchY < 0.3 ? 1 : (touchY > 0.7 ? -1 : 0);
        });
        window.addEventListener('touchend', () => { state.input.x = 0; state.input.y = 0; });

        function update() {
            if(!state.running) return;

            // Physics & Movement
            state.speed += SETTINGS.ACCEL;
            state.speed = Math.min(state.speed, SETTINGS.MAX_SPEED);
            state.maxSpeedReached = Math.max(state.maxSpeedReached, state.speed);

            // Banking/Rotation
            const targetRotZ = -state.input.x * 0.6;
            const targetRotX = state.input.y * 0.3;
            craftGroup.rotation.z = THREE.MathUtils.lerp(craftGroup.rotation.z, targetRotZ, SETTINGS.BANK_SPEED);
            craftGroup.rotation.x = THREE.MathUtils.lerp(craftGroup.rotation.x, targetRotX, SETTINGS.BANK_SPEED);

            // Position
            state.playerPos.x += state.input.x * SETTINGS.SENSITIVITY * 10;
            state.playerPos.y += state.input.y * SETTINGS.SENSITIVITY * 10;
            state.playerPos.z -= state.speed;

            // Constraints
            state.playerPos.y = Math.max(-1, Math.min(10, state.playerPos.y));
            state.playerPos.x = Math.max(-20, Math.min(20, state.playerPos.x));

            craftGroup.position.copy(state.playerPos);

            // Camera follow
            camera.position.lerp(new THREE.Vector3(state.playerPos.x * 0.5, state.playerPos.y + 1.5, state.playerPos.z + 5), 0.1);
            camera.lookAt(state.playerPos.x, state.playerPos.y, state.playerPos.z - 10);
            camera.fov = 75 + (state.speed * 10);
            camera.updateProjectionMatrix();

            // Energy & Scoring
            state.energy -= SETTINGS.ENERGY_DECAY;
            state.score += state.speed * state.multiplier;

            // Collision Detection
            const playerBox = new THREE.Box3().setFromObject(craftGroup);
            
            // Near miss check
            let nearMiss = false;
            obstacles.forEach(obj => {
                const obsBox = new THREE.Box3().setFromObject(obj);
                if(playerBox.intersectsBox(obsBox)) {
                    gameOver();
                } else {
                    const dist = playerBox.distanceToBox(obsBox);
                    if(dist < 2) {
                        nearMiss = true;
                        state.multiplier = Math.min(state.multiplier + 0.01, 10);
                    }
                }
            });

            if(nearMiss) {
                document.getElementById('multiplier').style.opacity = 1;
                document.getElementById('multiplier').innerText = `x${state.multiplier.toFixed(1)} NEAR MISS!`;
                document.getElementById('multiplier').style.transform = 'scale(1.2)';
                setTimeout(() => { document.getElementById('multiplier').style.transform = 'scale(1)'; }, 100);
            } else {
                document.getElementById('multiplier').style.opacity = 0;
                state.multiplier = Math.max(1, state.multiplier * 0.99);
            }

            // Collectibles
            for(let i = collectibles.length - 1; i >= 0; i--) {
                const orb = collectibles[i];
                if(craftGroup.position.distanceTo(orb.position) < 2) {
                    state.energy = Math.min(100, state.energy + SETTINGS.ENERGY_GAIN);
                    playSound(600, 'sine', 0.2);
                    orb.visible = false;
                    collectibles.splice(i, 1);
                    // Need to remove from parent chunk? Not strictly necessary if hidden.
                }
            }

            if(state.energy <= 0) gameOver();

            // Chunk Management
            if(state.playerPos.z < chunks[0].z - SETTINGS.CHUNK_SIZE) {
                const old = chunks.shift();
                scene.remove(old.group);
                // Clean up obstacles/collectibles associated with this chunk
                // In a full build, we'd map them. Here we just filter by Z.
                const cutZ = old.z - 50;
                for(let i = obstacles.length-1; i>=0; i--) {
                    if(obstacles[i].position.z > -cutZ) obstacles.splice(i, 1);
                }
                createChunk(chunks[chunks.length-1].z - SETTINGS.CHUNK_SIZE);
            }

            // UI Update
            document.getElementById('score').innerText = Math.floor(state.score);
            document.getElementById('energy-bar').style.width = state.energy + '%';
            document.getElementById('speed-val').innerText = `SPEED: ${Math.floor(state.speed * 400)} KM/H`;

            // Audio Update
            if(engineOsc) {
                engineOsc.frequency.setTargetAtTime(50 + (state.speed * 50), audioCtx.currentTime, 0.1);
            }
        }

        function gameOver() {
            state.running = false;
            playSound(100, 'sawtooth', 0.5, 0.3);
            document.getElementById('overlay').style.display = 'flex';
            document.getElementById('title').innerText = "CRASHED";
            document.getElementById('game-over-stats').style.display = 'block';
            document.getElementById('final-score').innerText = `SCORE: ${Math.floor(state.score)}`;
            document.getElementById('final-speed').innerText = `MAX SPEED: ${Math.floor(state.maxSpeedReached * 400)} KM/H`;
            document.getElementById('start-btn').innerText = "Restart";
        }

        function reset() {
            state.score = 0;
            state.energy = 100;
            state.speed = SETTINGS.START_SPEED;
            state.multiplier = 1;
            state.maxSpeedReached = 0;
            state.playerPos.set(0, 0, 0);
            craftGroup.position.set(0, 0, 0);
            
            // Clear chunks and rebuild
            chunks.forEach(c => scene.remove(c.group));
            chunks.length = 0;
            obstacles.length = 0;
            collectibles.length = 0;
            for(let i=0; i<SETTINGS.CHUNK_COUNT; i++) {
                createChunk(-i * SETTINGS.CHUNK_SIZE);
            }

            document.getElementById('overlay').style.display = 'none';
            state.running = true;
        }

        document.getElementById('start-btn').addEventListener('click', () => {
            if(!audioCtx) initAudio();
            reset();
        });

        function animate() {
            requestAnimationFrame(animate);
            update();
            composer.render();
        }

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

        animate();
    </script>
</body>
</html>
<!-- agent-meta {"model":"google/gemma-4-31b-it","provider":"openrouter","persona":"basic","sessionId":"182736ac-455d-48ac-a81b-bddebfc43142","tokensIn":979,"tokensOut":5190,"tokensTotal":6169,"turns":1,"toolCalls":0,"failedToolCalls":0,"timestamp":"2026-07-14T14:38:37.118Z"} -->