← Canyon Run results

Canyon Run

lfm2 24b a2b · basic

Initial view of Canyon Run

Browser check: Artifact runtime error. This is a technical check, not a quality review.

Reviews & generation details

Reviews

No human review yet. Unreviewed does not mean unsuccessful.

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 11,921 bytes · SHA-256 4f6206970676
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>High-Speed Procedural Canyon Racer</title>
    <style>
        body { margin: 0; overflow: hidden; background: #1a0f2c; }
        canvas { display: block; }
        #hud {
            position: absolute;
            top: 10px;
            left: 10px;
            color: #00ffcc;
            font-family: 'Courier New', monospace;
            background: rgba(0,0,0,0.5);
            padding: 8px 16px;
            border-radius: 4px;
        }
        #energyBar {
            width: 200px; height: 20px; background: #222; border-radius: 10px;
            margin-top: 5px; position: relative;
        }
        #energyBar::before {
            content: '';
            display: block; height: 100%; background: #00ffcc; border-radius: 10px;
        }
        #scoreText { font-size: 24px; color: #ffd700; margin-top: 5px; }
    </style>
</head>
<body>
    <div id="hud">
        <div id="energyBar"></div>
        <div id="scoreText">Score: 0 | Multiplier: 1x</div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/three@0.158.0/build/three.min.js"></script>
    <script>
        const scene = new THREE.Scene();
        const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 1, 1000);
        const renderer = new THREE.WebGLRenderer({ antialias: true });
        renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(renderer.domElement);

        // Lighting
        const light = new THREE.DirectionalLight(0xffffff, 1);
        light.position.set(100, 200, 100);
        scene.add(light);

        // Player craft (low-poly cube)
        const geometry = new THREE.BoxGeometry(2, 2, 2);
        const material = new THREE.MeshStandardMaterial({ color: 0x00ffcc });
        const craft = new THREE.Mesh(geometry, material);
        scene.add(craft);

        // Camera follow
        camera.position.set(0, 5, 10);
        camera.lookAt(0, 0, 0);

        // Procedural terrain generator
        let chunks = {};
        const chunkSize = 20;
        const heightMap = (x, z) => Math.sin(x/10)*Math.cos(z/10)*4 + 2;

        function generateChunk(x, z) {
            const geometry = new THREE.BufferGeometry();
            const vertices = [];
            for(let x=0; x<chunkSize; x++) {
                for(let z=0; z<chunkSize; z++) {
                    const vx = x + x*0.1 + x*0.01*Math.random();
                    const vz = z + z*0.1 + z*0.01*Math.random();
                    const y = heightMap(vx, vz) + craft.position.y;
                    vertices.push(vx, y, vz);
                }
            }
            geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
            const mesh = new THREE.Mesh(geometry, new THREE.MeshStandardMaterial({ color: 0x222222 }));
            mesh.position.set(x*chunkSize, 0, z*chunkSize);
            scene.add(mesh);
            chunks[`${x},${z}`] = mesh;
        }

        function updateChunks() {
            const camPos = craft.position;
            // Generate new chunks ahead
            for(let x=Math.floor(camPos.x/chunkSize)-2; x<=Math.ceil(camPos.x/chunkSize)+3; x++) {
                for(let z=Math.floor(camPos.z/chunkSize)-2; z<=Math.ceil(camPos.z/chunkSize)+3; z++) {
                    if(!chunks[`${x},${z}`]) generateChunk(x, z);
                }
            }
            // Remove far chunks
            for(let k in chunks) {
                if(!(
                    Math.abs(parseInt(k.split(',')[0]) - camPos.x/chunkSize) > 3 ||
                    Math.abs(parseInt(k.split(',')[1]) - camPos.z/chunkSize) > 3
                )) {
                    scene.remove(chunks[k]);
                    delete chunks[k];
                }
            }
        }

        // Physics variables
        let velocity = new THREE.Vector3(0, 0, 0);
        let acceleration = new THREE.Vector3(0, 0, 0);
        let energy = 100;
        let turbo = 0;
        let multiplier = 1;
        let score = 0;

        // Input
        const keys = {};
        window.addEventListener('keydown', e => keys[e.code] = true);
        window.addEventListener('keyup', e => keys[e.code] = false);

        function applyPhysics() {
            // Flight physics: momentum, banking
            velocity.add(acceleration.clone().multiplyScalar(0.1));
            velocity.multiplyScalar(0.98);
            craft.position.add(velocity);

            // Pitch acceleration (forward)
            if(keys['KeyW']) velocity.z += 0.05;
            if(keys['KeyS']) velocity.z -= 0.05;
            if(keys['KeyA']) velocity.x -= 0.05;
            if(keys['KeyD']) velocity.x += 0.05;

            // Banking (turn)
            if(keys['ArrowLeft']) craft.rotation.y -= 0.01;
            if(keys['ArrowRight']) craft.rotation.y += 0.01;

            // Energy decay
            energy -= 0.05;
            if(energy < 0) energy = 0;

            // Turbo meter
            turbo = Math.min(1, turbo + (velocity.length() * 0.02));
            if(turbo > 1) turbo = 1;

            // Score multiplier
            const distToWalls = getNearestWallDistance(craft.position);
            if(distToWalls < 2 && distToWalls > 0) multiplier = Math.min(5, multiplier + 0.05 * (2-distToWalls));

            // Energy bar
            document.getElementById('energyBar').style.width = energy + '%';
        }

        function getNearestWallDistance(pos) {
            let min = 100;
            for(let k in chunks) {
                const m = chunks[k].position;
                const vx = pos.x - m.x, vz = pos.z - m.z;
                const dist = Math.sqrt(vx*vx + vz*vz);
                if(dist < 2) min = Math.min(min, dist);
            }
            return min;
        }

        // Collectibles (energy orbs)
        function spawnOrb() {
            const size = 0.5 + Math.random()*0.3;
            const geometry = new THREE.SphereGeometry(size, 16, 16);
            const material = new THREE.MeshStandardMaterial({ color: 0xffcc00 });
            const orb = new THREE.Mesh(geometry, material);
            orb.position.set(
                Math.random()*chunkSize + chunkSize/2,
                heightMap(orb.position.x, orb.position.z) + 1.5,
                Math.random()*chunkSize + chunkSize/2
            );
            scene.add(orb);

            // Physics
            orb.userData = { type: 'orb', onCollide: () => {
                score += 100 * multiplier;
                energy = Math.min(100, energy + 30);
                scoreText.innerHTML = "Score: " + Math.floor(score) + " | Multiplier: " + Math.floor(multiplier);
            }};
        }

        // Particles
        function createParticleSystem() {
            const particles = new THREE.Geometry();
            for(let i=0; i<200; i++) {
                const p = new THREE.Vector3(
                    craft.position.x + (Math.random()-0.5)*chunkSize,
                    craft.position.y + 1,
                    craft.position.z + (Math.random()-0.5)*chunkSize
                );
                particles.addPoint(p);
            }
            const material = new THREE.PointsMaterial({ color: 0xffffff, size: 0.1 });
            return new THREE.Points(particles, material);
        }

        // Post-processing
        let bloom = new THREE.BloomEffect(renderer, {
            intensity: 1.2,
            threshold: 0.4,
            color: 0xffffff
        });
        renderer.bloom = bloom;

        // Render loop
        function animate() {
            requestAnimationFrame(animate);
            applyPhysics();
            updateChunks();
            // Orb spawning
            if(Math.random()<0.005) spawnOrb();
            // Camera shake on close
            const dist = craft.position.distanceTo(craft.position.clone().add(new THREE.Vector3(0,5,10)));
            camera.position.y += (Math.sin(dist/8)*0.05);
            camera.position.z += (Math.cos(dist/8)*0.03);
            // Render
            renderer.render(scene, camera);
        }
        animate();

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

        // HUD update
        setInterval(() => {
            document.getElementById('scoreText').innerHTML = "Score: " + Math.floor(score) + " | Multiplier: " + Math.floor(multiplier);
            document.getElementById('energyBar').style.width = energy + '%';
        }, 100);

        // Collision detection
        function checkCollisions() {
            for(let k in chunks) {
                const mesh = chunks[k];
                const box = new THREE.Box3().setFromObject(mesh);
                if(box.intersectsSphere(craft.position, 2.5)) {
                    // Near miss
                    multiplier = Math.min(5, multiplier + 0.1);
                }
            }
        }

        // Audio (Web Audio API)
        const ctx = new (window.AudioContext || window.webkitAudioContext)();
        function playEngine() {
            const osc = ctx.createOscillator();
            osc.type = 'sine';
            osc.frequency.setValueAtTime(120 + Math.sin(Date.now()/500), false);
            osc.connect(ctx.destination);
            osc.start();
            osc.stop(Date.now()/1000 + 0.2);
        }
        function playCollect() {
            const p = new AudioContext().createOscillator();
            p.type = 'square';
            p.frequency.setValueAtTime(800, ctx.currentTime);
            p.connect(ctx.destination);
            p.start();
            p.stop(Date.now()/1000 + 0.1);
        }
        function playNearMiss() {
            const p = new AudioContext().createOscillator();
            p.type = 'sine';
            p.frequency.setValueAtTime(300, ctx.currentTime);
            p.connect(ctx.destination);
            p.start();
            p.stop(Date.now()/1000 + 0.2);
        }

        // Game Over screen
        function gameOver() {
            const overlay = document.createElement('div');
            overlay.style = `
                position: fixed; top:0; left:0; width:100vw; height:100vh;
                background: rgba(0,0,0,0.9); color: #fff; font-size: 2em; text-align:center; padding: 40px;
                z-index:9999; display: flex; flex-direction:column; align-items: center;
            `;
            overlay.innerHTML = `
                <h1>Game Over</h1>
                <div>Score: ${Math.floor(score)}</div>
                <div>Max Speed: ${Math.floor(velocity.length()*2)}</div>
                <button id="restartBtn" style="margin-top:20px; padding:10px 30px; background:#fff; color:#222">Restart</button>
            `;
            document.body.appendChild(overlay);
            document.getElementById('restartBtn').onclick = () => {
                // Reset
                scene.traverse(o => { if(o.geometry) o.geometry.dispose(); });
                chunks = {};
                score=0; energy=100; multiplier=1; velocity.set(0,0,0); turbo=0;
                document.body.removeChild(overlay);
                animate();
            };
        }

        // Input for boost
        window.addEventListener('keydown', e => {
            if(e.code === 'KeyX' && energy>0) {
                turbo = Math.min(1, turbo+0.5);
                playNearMiss();
            }
        });

        // Initial chunk
        generateChunk(0,0);
    </script>
</body>
</html>
<!-- agent-meta {"model":"liquid/lfm2-24b-a2b","provider":"lmstudio","persona":"basic","sessionId":"17bdd4a6-b885-4162-b70e-0b261b914198","tokensIn":1012,"tokensOut":3132,"tokensTotal":4144,"cost":0,"turns":1,"toolCalls":0,"failedToolCalls":0,"timestamp":"2026-08-01T04:49:32.903Z"} -->