← Canyon Run results

Canyon Run

ThinkingCap Qwen3.6 27B GGUF · typescript

Initial view of Canyon Run

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 37,402 bytes · SHA-256 ed65169efdcf
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Canyon Racer</title>
<script src="https://cdn.jsdelivr.net/npm/three@0.157.0/build/three.min.js"></script>
<style>
/* ── css: game ── */
* { margin: 0; padding: 0; box-sizing: border-box; }
html, body { width: 100%; height: 100%; overflow: hidden; background: #0a0510; font-family: 'Segoe UI', 'Helvetica Neue', Arial, sans-serif; }
#game-container { width: 100%; height: 100%; position: relative; }
#game-canvas { width: 100%; height: 100%; display: block; }

/* HUD */
#hud { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; }
#speed-container { position: absolute; right: 30px; top: 50%; transform: translateY(-50%); width: 6px; height: 200px; background: rgba(255,255,255,0.1); border-radius: 3px; }
#speed-bar { position: absolute; bottom: 0; width: 100%; height: 0%; background: linear-gradient(to top, #ff6a00, #ffaa00); border-radius: 3px; transition: height 0.1s; }
#multiplier { position: absolute; right: 50px; top: 50%; transform: translateY(-50%); font-size: 48px; font-weight: 900; color: #ffaa00; text-shadow: 0 0 20px rgba(255,170,0,0.5); opacity: 0; transition: opacity 0.3s, transform 0.1s; }
#multiplier.active { opacity: 1; }
#energy-container { position: absolute; bottom: 30px; left: 50%; transform: translateX(-50%); width: 300px; height: 8px; background: rgba(255,255,255,0.1); border-radius: 4px; }
#energy-bar { width: 100%; height: 100%; background: linear-gradient(to right, #ff3366, #ff6a00, #ffaa00); border-radius: 4px; transition: width 0.15s; }
#turbo-container { position: absolute; bottom: 50px; left: 50%; transform: translateX(-50%); width: 200px; height: 4px; background: rgba(255,255,255,0.08); border-radius: 2px; }
#turbo-bar { width: 0%; height: 100%; background: #00ffff; border-radius: 2px; box-shadow: 0 0 10px #00ffff; transition: width 0.2s; }
#score-display { position: absolute; top: 20px; left: 50%; transform: translateX(-50%); font-size: 24px; font-weight: 300; color: rgba(255,255,255,0.7); letter-spacing: 4px; }

/* Screens */
#start-screen, #game-over { position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; background: rgba(10,5,16,0.85); pointer-events: auto; }
#start-screen h1, #game-over h1 { font-size: 64px; font-weight: 900; color: #ffaa00; text-shadow: 0 0 40px rgba(255,170,0,0.4); letter-spacing: 8px; margin-bottom: 10px; }
#start-screen p { color: rgba(255,255,255,0.5); margin-bottom: 30px; font-size: 14px; letter-spacing: 2px; }
#game-over div { font-size: 20px; color: rgba(255,255,255,0.7); margin: 8px 0; letter-spacing: 2px; }
#final-score { font-size: 36px !important; color: #ffaa00 !important; font-weight: 700; }
#max-speed { color: #00ffff !important; }
button { background: none; border: 2px solid #ffaa00; color: #ffaa00; padding: 12px 40px; font-size: 18px; letter-spacing: 4px; cursor: pointer; pointer-events: auto; transition: all 0.2s; font-family: inherit; }
button:hover { background: #ffaa00; color: #0a0510; }
</style>
</head>
<body>
<div id="game-container">
  <canvas id="game-canvas"></canvas>
  <div id="hud">
    <div id="speed-container">
      <div id="speed-bar"></div>
    </div>
    <div id="multiplier"></div>
    <div id="energy-container">
      <div id="energy-bar"></div>
    </div>
    <div id="turbo-container">
      <div id="turbo-bar"></div>
    </div>
    <div id="score-display">0</div>
  </div>
  <div id="game-over" style="display:none">
    <h1>GAME OVER</h1>
    <div id="final-score">0</div>
    <div id="max-speed">0</div>
    <button id="restart-btn">RESTART</button>
  </div>
  <div id="start-screen">
    <h1>CANYON RACER</h1>
    <p>WASD / Arrow Keys to fly • Space to boost</p>
    <button id="start-btn">LAUNCH</button>
  </div>
</div>
<script>
(function () {
'use strict';
var __mods = {};
var __cache = {};
var __map = {"src/main.ts":{"./state":"src/state.ts","./input":"src/input.ts","./player":"src/player.ts","./chunks":"src/chunks.ts","./particles":"src/particles.ts","./audio":"src/audio.ts"},"src/player.ts":{"./input":"src/input.ts","./state":"src/state.ts"},"src/chunks.ts":{"./state":"src/state.ts"}};
function __require(id) {
  if (__cache[id]) return __cache[id].exports;
  var module = __cache[id] = { exports: {} };
  var factory = __mods[id];
  if (!factory) throw new Error("Module not found: " + id);
  factory(module.exports, function (spec) {
    var target = (__map[id] && __map[id][spec]) || spec;
    return __require(target);
  }, module);
  return module.exports;
}

// ── module: src/main.ts ──
__mods["src/main.ts"] = function (exports, require, module) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const state_1 = require("./state");
const input_1 = require("./input");
const player_1 = require("./player");
const chunks_1 = require("./chunks");
const particles_1 = require("./particles");
const audio_1 = require("./audio");
// --- Globals ---
let renderer;
let scene;
let camera;
let player;
let chunkManager;
let particles;
let audio;
// Post-processing
let composerRT = null;
let composerRT2 = null;
let quadMesh;
let quadScene;
let quadCamera;
let thresholdShader;
let blurShader;
let compositeShader;
// Camera shake
let shakeAmount = 0;
// HUD elements
let speedBar;
let multiplierEl;
let energyBar;
let turboBar;
let scoreDisplay;
let gameOverScreen;
let startScreen;
let finalScoreEl;
let maxSpeedEl;
let clock;
let playerZ = 0;
function init() {
    (0, input_1.initInput)();
    const canvas = document.getElementById('game-canvas');
    // Renderer
    renderer = new THREE.WebGLRenderer({
        canvas,
        antialias: true,
        alpha: false,
    });
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
    renderer.setClearColor(0x0a0510, 1);
    // Scene
    scene = new THREE.Scene();
    scene.fog = new THREE.Fog(0x1a0a20, 100, 350);
    // Camera
    camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.1, 600);
    camera.position.set(0, 2, 8);
    camera.lookAt(0, 0, -20);
    // Lighting — cyber sunset
    const sunLight = new THREE.DirectionalLight(0xff8844, 1.5);
    sunLight.position.set(30, 40, -50);
    scene.add(sunLight);
    const ambient = new THREE.AmbientLight(0x221133, 0.6);
    scene.add(ambient);
    const hemiLight = new THREE.HemisphereLight(0xff6633, 0x110022, 0.5);
    scene.add(hemiLight);
    const backLight = new THREE.DirectionalLight(0x6633ff, 0.5);
    backLight.position.set(-20, 10, 30);
    scene.add(backLight);
    // Player
    player = new player_1.Player();
    scene.add(player.mesh);
    // Chunk system
    chunkManager = new chunks_1.ChunkManager();
    for (const chunk of chunkManager.chunks) {
        scene.add(chunk.mesh);
    }
    // Particles
    particles = new particles_1.ParticleSystem();
    particles.init(scene);
    // Audio
    audio = new audio_1.AudioEngine();
    // Clock
    clock = new THREE.Clock();
    // Post-processing quad
    // Quad for potential post-processing (not used in this version)
    // HUD refs
    speedBar = document.getElementById('speed-bar');
    multiplierEl = document.getElementById('multiplier');
    energyBar = document.getElementById('energy-bar');
    turboBar = document.getElementById('turbo-bar');
    scoreDisplay = document.getElementById('score-display');
    gameOverScreen = document.getElementById('game-over');
    startScreen = document.getElementById('start-screen');
    finalScoreEl = document.getElementById('final-score');
    maxSpeedEl = document.getElementById('max-speed');
    document.getElementById('start-btn').addEventListener('click', startGame);
    document.getElementById('restart-btn').addEventListener('click', restartGame);
    window.addEventListener('resize', onResize);
    requestAnimationFrame(renderLoop);
}
function startGame() {
    startScreen.style.display = 'none';
    state_1.state.running = true;
    audio.init();
}
function restartGame() {
    Object.assign(state_1.state, (0, state_1.initialGameState)());
    player.mesh.position.set(0, 0, 0);
    player.mesh.rotation.set(0, 0, 0);
    player.velocity.set(0, 0, 0);
    playerZ = 0;
    for (const chunk of chunkManager.chunks) {
        scene.remove(chunk.mesh);
        for (const child of chunk.mesh.children) {
            child.geometry?.dispose();
            child.material?.dispose();
        }
    }
    chunkManager.chunks = [];
    chunkManager.nextChunkZ = 0;
    chunkManager = new chunks_1.ChunkManager();
    for (const chunk of chunkManager.chunks) {
        scene.add(chunk.mesh);
    }
    gameOverScreen.style.display = 'none';
    state_1.state.running = true;
    state_1.state.gameOver = false;
}
function onResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
}
function updateHUD() {
    const speedPct = Math.min(100, (state_1.state.speed / 80) * 100);
    speedBar.style.height = speedPct + '%';
    if (state_1.state.nearMissTimer > 0 && state_1.state.multiplier > 1) {
        multiplierEl.textContent = 'x' + state_1.state.multiplier.toFixed(1);
        multiplierEl.classList.add('active');
    }
    else {
        multiplierEl.classList.remove('active');
    }
    energyBar.style.width = state_1.state.energy + '%';
    if (state_1.state.energy < 20) {
        energyBar.style.background = '#ff3366';
    }
    else {
        energyBar.style.background = '';
    }
    turboBar.style.width = state_1.state.turbo + '%';
    scoreDisplay.textContent = Math.floor(state_1.state.score).toLocaleString();
}
function triggerShake(amount) {
    shakeAmount = amount;
}
function triggerGameOver() {
    state_1.state.gameOver = true;
    state_1.state.running = false;
    audio.playCrash();
    triggerShake(1.5);
    finalScoreEl.textContent = Math.floor(state_1.state.score).toLocaleString();
    maxSpeedEl.textContent = 'Max Speed: ' + Math.floor(state_1.state.maxSpeed);
    gameOverScreen.style.display = 'flex';
}
function renderLoop() {
    requestAnimationFrame(renderLoop);
    const dt = Math.min(clock.getDelta(), 0.05);
    if (!state_1.state.running || state_1.state.gameOver) {
        renderer.render(scene, camera);
        return;
    }
    // Speed management
    const baseSpeed = state_1.state.speed;
    const currentSpeed = player.isBoosting ? baseSpeed * 1.8 : baseSpeed;
    state_1.state.speed = Math.min(80, state_1.state.speed + dt * 0.5);
    state_1.state.maxSpeed = Math.max(state_1.state.maxSpeed, state_1.state.speed);
    state_1.state.difficulty = 1 + state_1.state.score / 5000;
    // Move forward
    playerZ += currentSpeed * dt;
    // Player update
    player.update(dt);
    // Move chunks
    for (const chunk of chunkManager.chunks) {
        chunk.mesh.position.z = chunk.z - playerZ;
    }
    // Chunk management
    chunkManager.update(playerZ);
    // Collision
    if (chunkManager.checkCollision(player.mesh.position, 1.5)) {
        triggerGameOver();
        return;
    }
    // Near-miss scoring
    const closestDist = chunkManager.checkNearMiss(player.mesh.position);
    if (closestDist < 7 && closestDist > 3) {
        if (state_1.state.nearMissTimer <= 0)
            audio.playNearMiss();
        state_1.state.multiplier = Math.min(10, state_1.state.multiplier + dt * 4);
        state_1.state.nearMissTimer = 2;
        triggerShake(0.12);
    }
    else {
        state_1.state.multiplier = Math.max(1, state_1.state.multiplier - dt * 1.5);
        state_1.state.nearMissTimer = Math.max(0, state_1.state.nearMissTimer - dt);
    }
    // Orb collection
    if (chunkManager.checkOrbCollection(player.mesh.position)) {
        audio.playCollect();
    }
    // Score
    state_1.state.score += currentSpeed * state_1.state.multiplier * dt;
    // Energy decay
    state_1.state.energy -= dt * 3;
    if (state_1.state.energy <= 0) {
        state_1.state.energy = 0;
        triggerGameOver();
        return;
    }
    // Turbo regen
    if (Math.abs(player.yaw) < 0.3 && Math.abs(player.pitch) < 0.3) {
        state_1.state.turbo = Math.min(100, state_1.state.turbo + dt * 5);
    }
    // Particles
    particles.addTrailPoint(player.mesh.position.x, player.mesh.position.y, player.mesh.position.z);
    particles.update(currentSpeed, dt);
    // Camera
    const targetFov = player.isBoosting ? 95 : 70;
    camera.fov += (targetFov - camera.fov) * dt * 3;
    camera.updateProjectionMatrix();
    const camTargetX = player.mesh.position.x * 0.35;
    const camTargetY = player.mesh.position.y * 0.35 + 2;
    camera.position.x += (camTargetX - camera.position.x) * dt * 4;
    camera.position.y += (camTargetY - camera.position.y) * dt * 4;
    camera.position.z = playerZ - (player.isBoosting ? 12 : 8);
    // Camera shake
    if (shakeAmount > 0.01) {
        camera.position.x += (Math.random() - 0.5) * shakeAmount;
        camera.position.y += (Math.random() - 0.5) * shakeAmount;
        shakeAmount *= 0.88;
    }
    camera.lookAt(player.mesh.position.x * 0.5, player.mesh.position.y * 0.3, playerZ - 40);
    // Engine audio
    audio.updateEngine(state_1.state.speed, player.isBoosting);
    // HUD
    updateHUD();
    // Render
    renderer.render(scene, camera);
}
init();
};

// ── types: globals.d.ts ──
__mods["globals.d.ts"] = function (exports) {};

// ── module: src/state.ts ──
__mods["src/state.ts"] = function (exports, require, module) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.state = exports.initialGameState = void 0;
const initialGameState = () => ({
    score: 0,
    multiplier: 1,
    energy: 100,
    turbo: 0,
    speed: 30,
    maxSpeed: 30,
    running: false,
    gameOver: false,
    difficulty: 1,
    nearMissTimer: 0,
});
exports.initialGameState = initialGameState;
exports.state = (0, exports.initialGameState)();
};

// ── module: src/input.ts ──
__mods["src/input.ts"] = function (exports, require, module) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.keys = void 0;
exports.initInput = initInput;
exports.isKey = isKey;
// Input manager — keyboard state
exports.keys = {};
function initInput() {
    window.addEventListener('keydown', (e) => {
        exports.keys[e.code] = true;
        if (['Space', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(e.code)) {
            e.preventDefault();
        }
    });
    window.addEventListener('keyup', (e) => {
        exports.keys[e.code] = false;
    });
}
function isKey(code) {
    return !!exports.keys[code];
}
};

// ── module: src/player.ts ──
__mods["src/player.ts"] = function (exports, require, module) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Player = void 0;
const input_1 = require("./input");
const state_1 = require("./state");
class Player {
    constructor() {
        this.velocity = new THREE.Vector3(0, 0, 0);
        this.pitch = 0;
        this.roll = 0;
        this.yaw = 0;
        this.targetPitch = 0;
        this.targetRoll = 0;
        this.targetYaw = 0;
        this.isBoosting = false;
        this.mesh = new THREE.Group();
        this.buildCraft();
    }
    buildCraft() {
        // Main body — sleek wedge
        const bodyMat = new THREE.MeshPhongMaterial({
            color: 0xcccccc,
            flatShading: true,
            emissive: 0x333333,
            emissiveIntensity: 0.3,
        });
        const bodyGeo = new THREE.ConeGeometry(0.6, 2.5, 4);
        const body = new THREE.Mesh(bodyGeo, bodyMat);
        body.rotation.x = Math.PI / 2;
        body.position.z = 0.3;
        this.mesh.add(body);
        // Cockpit
        const cockpitGeo = new THREE.ConeGeometry(0.3, 1.2, 4);
        const cockpitMat = new THREE.MeshPhongMaterial({
            color: 0x00ffff,
            flatShading: true,
            emissive: 0x00ffff,
            emissiveIntensity: 0.8,
        });
        const cockpit = new THREE.Mesh(cockpitGeo, cockpitMat);
        cockpit.rotation.x = -Math.PI / 2;
        cockpit.position.z = 0.5;
        cockpit.position.y = 0.15;
        this.mesh.add(cockpit);
        // Wings
        const wingGeo = new THREE.BoxGeometry(4, 0.08, 1.2);
        const wingMat = new THREE.MeshPhongMaterial({
            color: 0xaaaaaa,
            flatShading: true,
        });
        const wings = new THREE.Mesh(wingGeo, wingMat);
        wings.position.z = 0.2;
        this.mesh.add(wings);
        // Wing tips (accent)
        const tipGeo = new THREE.BoxGeometry(0.3, 0.15, 0.8);
        const tipMat = new THREE.MeshPhongMaterial({
            color: 0xff6a00,
            flatShading: true,
            emissive: 0xff6a00,
            emissiveIntensity: 0.5,
        });
        const leftTip = new THREE.Mesh(tipGeo, tipMat);
        leftTip.position.set(-2.1, 0, 0.2);
        this.mesh.add(leftTip);
        const rightTip = new THREE.Mesh(tipGeo, tipMat);
        rightTip.position.set(2.1, 0, 0.2);
        this.mesh.add(rightTip);
        // Engine glow
        const engineGeo = new THREE.CylinderGeometry(0.2, 0.4, 0.6, 8);
        const engineMat = new THREE.MeshPhongMaterial({
            color: 0xff4400,
            flatShading: true,
            emissive: 0xff4400,
            emissiveIntensity: 2,
        });
        const engine = new THREE.Mesh(engineGeo, engineMat);
        engine.rotation.x = Math.PI / 2;
        engine.position.z = 1.6;
        engine.userData.isEngine = true;
        this.mesh.add(engine);
    }
    update(dt) {
        const accel = 15;
        const turnSpeed = 3.5;
        // Pitch control (up/down)
        this.targetPitch = 0;
        if ((0, input_1.isKey)('ArrowUp') || (0, input_1.isKey)('KeyW'))
            this.targetPitch = -turnSpeed;
        if ((0, input_1.isKey)('ArrowDown') || (0, input_1.isKey)('KeyS'))
            this.targetPitch = turnSpeed;
        // Yaw control (left/right)
        this.targetYaw = 0;
        if ((0, input_1.isKey)('ArrowLeft') || (0, input_1.isKey)('KeyA'))
            this.targetYaw = turnSpeed;
        if ((0, input_1.isKey)('ArrowRight') || (0, input_1.isKey)('KeyD'))
            this.targetYaw = -turnSpeed;
        // Roll follows yaw
        this.targetRoll = -this.targetYaw * 0.6;
        // Boost
        this.isBoosting = (0, input_1.isKey)('Space') && state_1.state.turbo > 0;
        if (this.isBoosting) {
            state_1.state.turbo = Math.max(0, state_1.state.turbo - 30 * dt);
        }
        // Smooth interpolation for banking
        const lerpFactor = Math.min(dt * 8, 1);
        this.pitch += (this.targetPitch - this.pitch) * lerpFactor;
        this.roll += (this.targetRoll - this.roll) * lerpFactor;
        this.yaw += (this.targetYaw - this.yaw) * lerpFactor;
        // Apply rotation to mesh
        this.mesh.rotation.x = this.pitch * 0.7;
        this.mesh.rotation.z = this.roll;
        this.mesh.rotation.y = this.yaw * 0.3;
        // Move position based on pitch/yaw inputs
        const moveSpeed = 25 * state_1.state.difficulty;
        this.velocity.x += this.yaw * dt * moveSpeed;
        this.velocity.y += this.pitch * dt * moveSpeed;
        // Damping
        this.velocity.x *= Math.pow(0.95, dt * 60);
        this.velocity.y *= Math.pow(0.95, dt * 60);
        this.mesh.position.x += this.velocity.x * dt;
        this.mesh.position.y += this.velocity.y * dt;
        // Clamp position
        this.mesh.position.x = Math.max(-35, Math.min(35, this.mesh.position.x));
        this.mesh.position.y = Math.max(-25, Math.min(25, this.mesh.position.y));
        // Engine glow intensity based on speed
        const engineMesh = this.mesh.children.find((c) => c.userData?.isEngine);
        if (engineMesh) {
            const intensity = this.isBoosting ? 4 : (state_1.state.speed / 50);
            engineMesh.material.emissiveIntensity = intensity;
            if (this.isBoosting) {
                engineMesh.scale.set(1.2, 1.2, 1.5);
            }
            else {
                engineMesh.scale.set(1, 1, 1);
            }
        }
    }
}
exports.Player = Player;
};

// ── module: src/chunks.ts ──
__mods["src/chunks.ts"] = function (exports, require, module) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ChunkManager = void 0;
const state_1 = require("./state");
const CHUNK_LENGTH = 200;
const CHUNK_COUNT = 8;
const ORB_COUNT_PER_CHUNK = 5;
const WALL_COLORS = [0x6b3510, 0x7b4523, 0x5b2510, 0x8b5030, 0x704020];
const MONOLITH_COLORS = [0x4a2060, 0x3a1550, 0x5a3070, 0x2a1040, 0x552266];
const ACCENT_COLORS = [0xff4400, 0xff8800, 0xcc2200, 0xff6600];
class ChunkManager {
    constructor() {
        this.chunks = [];
        this.nextChunkZ = 0;
        for (let i = 0; i < CHUNK_COUNT; i++) {
            this.addChunk(this.nextChunkZ);
            this.nextChunkZ += CHUNK_LENGTH;
        }
    }
    addChunk(z) {
        const difficulty = state_1.state.difficulty;
        const baseWidth = Math.max(10, 38 - difficulty * 3);
        const chunk = new THREE.Group();
        const variation = Math.sin(z * 0.01) * 5;
        const leftWallX = -(baseWidth + 4 + variation);
        const rightWallX = baseWidth + 4 - variation;
        // Main canyon walls — multi-segment for visual depth
        const segments = 4;
        for (let s = 0; s < segments; s++) {
            const segZ = (s - segments / 2) * (CHUNK_LENGTH / segments);
            const segW = 6 + Math.random() * 6;
            const wallH = 35 + Math.random() * 25;
            // Left wall
            const lGeo = new THREE.BoxGeometry(segW, wallH, CHUNK_LENGTH / segments + 1);
            const lMat = new THREE.MeshPhongMaterial({
                color: WALL_COLORS[Math.floor(Math.random() * WALL_COLORS.length)],
                flatShading: true,
            });
            const lWall = new THREE.Mesh(lGeo, lMat);
            lWall.position.set(leftWallX + Math.sin(s * 1.5) * 3, wallH / 2 - 8, segZ);
            chunk.add(lWall);
            // Right wall
            const rGeo = new THREE.BoxGeometry(segW, wallH, CHUNK_LENGTH / segments + 1);
            const rMat = new THREE.MeshPhongMaterial({
                color: WALL_COLORS[Math.floor(Math.random() * WALL_COLORS.length)],
                flatShading: true,
            });
            const rWall = new THREE.Mesh(rGeo, rMat);
            rWall.position.set(rightWallX + Math.cos(s * 1.5) * 3, wallH / 2 - 8, segZ);
            chunk.add(rWall);
            // Wall accent strips (glowing edges)
            const stripGeo = new THREE.BoxGeometry(0.3, wallH * 0.6, 1);
            const stripMat = new THREE.MeshPhongMaterial({
                color: ACCENT_COLORS[Math.floor(Math.random() * ACCENT_COLORS.length)],
                flatShading: true,
                emissive: 0xff4400,
                emissiveIntensity: 0.4,
            });
            const stripL = new THREE.Mesh(stripGeo, stripMat);
            stripL.position.set(leftWallX + segW / 2, wallH / 2 - 8, segZ);
            chunk.add(stripL);
            const stripR = new THREE.Mesh(stripGeo, stripMat);
            stripR.position.set(rightWallX - segW / 2, wallH / 2 - 8, segZ);
            chunk.add(stripR);
        }
        // Ground
        const groundGeo = new THREE.PlaneGeometry(baseWidth * 2 + 30, CHUNK_LENGTH + 2);
        const groundMat = new THREE.MeshPhongMaterial({
            color: 0x1a0a15,
            flatShading: true,
        });
        const ground = new THREE.Mesh(groundGeo, groundMat);
        ground.rotation.x = -Math.PI / 2;
        ground.position.y = -25;
        chunk.add(ground);
        // Ceiling
        const ceilGeo = new THREE.PlaneGeometry(baseWidth * 2 + 30, CHUNK_LENGTH + 2);
        const ceilMat = new THREE.MeshPhongMaterial({
            color: 0x120520,
            flatShading: true,
        });
        const ceil = new THREE.Mesh(ceilGeo, ceilMat);
        ceil.rotation.x = Math.PI / 2;
        ceil.position.y = 25;
        chunk.add(ceil);
        // Floating monoliths
        const monolithCount = Math.floor(2 + difficulty * 1.5);
        for (let i = 0; i < monolithCount; i++) {
            const h = 5 + Math.random() * 12;
            const w = 1 + Math.random() * 2.5;
            const d = 1 + Math.random() * 2.5;
            const mGeo = new THREE.BoxGeometry(w, h, d);
            const mMat = new THREE.MeshPhongMaterial({
                color: MONOLITH_COLORS[Math.floor(Math.random() * MONOLITH_COLORS.length)],
                flatShading: true,
                emissive: 0x220044,
                emissiveIntensity: 0.3,
            });
            const monolith = new THREE.Mesh(mGeo, mMat);
            monolith.position.set((Math.random() - 0.5) * (baseWidth * 1.2), (Math.random() - 0.5) * 16, (Math.random() - 0.5) * (CHUNK_LENGTH - 30));
            monolith.rotation.y = Math.random() * Math.PI;
            chunk.add(monolith);
        }
        // Tight squeezes
        if (difficulty > 1.3 && Math.random() > 0.4) {
            const squeezeZ = (Math.random() - 0.5) * (CHUNK_LENGTH - 40);
            const gapX = (Math.random() - 0.5) * baseWidth * 0.5;
            const gapY = (Math.random() - 0.5) * 10;
            const gapSize = Math.max(3.5, 8 - difficulty * 0.5);
            const sqGeo = new THREE.BoxGeometry(baseWidth + 10, 50, 2);
            const sqMat = new THREE.MeshPhongMaterial({
                color: 0x3a1030,
                flatShading: true,
            });
            const topW = new THREE.Mesh(sqGeo, sqMat);
            topW.position.set(gapX, gapY + gapSize / 2 + 2.5, squeezeZ);
            chunk.add(topW);
            const botW = new THREE.Mesh(sqGeo, sqMat);
            botW.position.set(gapX, gapY - gapSize / 2 - 2.5, squeezeZ);
            chunk.add(botW);
        }
        chunk.position.z = -z;
        // Energy orbs
        const orbs = [];
        const orbGeo = new THREE.SphereGeometry(0.5, 6, 6);
        for (let i = 0; i < ORB_COUNT_PER_CHUNK; i++) {
            const orbMat = new THREE.MeshPhongMaterial({
                color: 0xffcc00,
                flatShading: true,
                emissive: 0xffaa00,
                emissiveIntensity: 2.5,
            });
            const orb = new THREE.Mesh(orbGeo, orbMat);
            orb.position.set((Math.random() - 0.5) * baseWidth * 1.2, (Math.random() - 0.5) * 16, (Math.random() - 0.5) * (CHUNK_LENGTH - 30));
            chunk.add(orb);
            orbs.push({ mesh: orb, collected: false });
        }
        this.chunks.push({ mesh: chunk, z, orbs, width: baseWidth });
    }
    update(playerZ) {
        while (this.chunks.length > 0 && this.chunks[0].z < playerZ - CHUNK_LENGTH * 2) {
            const oldChunk = this.chunks.shift();
            for (const child of oldChunk.mesh.children) {
                child.geometry?.dispose();
                child.material?.dispose();
            }
        }
        const lastChunk = this.chunks[this.chunks.length - 1];
        if (lastChunk && this.chunks.length < CHUNK_COUNT) {
            this.addChunk(lastChunk.z + CHUNK_LENGTH);
        }
    }
    checkOrbCollection(playerPos) {
        let collected = false;
        for (const chunk of this.chunks) {
            for (const orb of chunk.orbs) {
                if (orb.collected)
                    continue;
                const orbWorldPos = new THREE.Vector3(orb.mesh.position.x, orb.mesh.position.y, -chunk.z + orb.mesh.position.z);
                if (playerPos.distanceTo(orbWorldPos) < 3) {
                    orb.collected = true;
                    orb.mesh.visible = false;
                    collected = true;
                    state_1.state.energy = Math.min(100, state_1.state.energy + 15);
                    state_1.state.turbo = Math.min(100, state_1.state.turbo + 20);
                }
            }
        }
        return collected;
    }
    checkCollision(playerPos, playerRadius) {
        for (const chunk of this.chunks) {
            const chunkLocalZ = playerPos.z + chunk.z;
            if (chunkLocalZ < -CHUNK_LENGTH / 2 || chunkLocalZ > CHUNK_LENGTH / 2)
                continue;
            const hw = chunk.width;
            if (Math.abs(playerPos.x) > hw - playerRadius)
                return true;
            if (Math.abs(playerPos.y) > 24 - playerRadius)
                return true;
            for (const child of chunk.mesh.children) {
                const mc = child;
                if (!mc.geometry)
                    continue;
                if (!(mc.geometry instanceof THREE.BoxGeometry))
                    continue;
                const wpos = new THREE.Vector3(mc.position.x, mc.position.y, -chunk.z + mc.position.z);
                const dx = Math.abs(playerPos.x - wpos.x);
                const dy = Math.abs(playerPos.y - wpos.y);
                const dz = Math.abs(playerPos.z - wpos.z);
                if (dx < 2 && dy < 4 && dz < 1.5)
                    return true;
            }
        }
        return false;
    }
    checkNearMiss(playerPos) {
        let closest = 999;
        for (const chunk of this.chunks) {
            const chunkLocalZ = playerPos.z + chunk.z;
            if (chunkLocalZ < -CHUNK_LENGTH / 2 || chunkLocalZ > CHUNK_LENGTH / 2)
                continue;
            const wallDist = chunk.width - Math.abs(playerPos.x);
            const ceilDist = 25 - Math.abs(playerPos.y);
            closest = Math.min(closest, wallDist, ceilDist);
        }
        return closest;
    }
}
exports.ChunkManager = ChunkManager;
};

// ── module: src/particles.ts ──
__mods["src/particles.ts"] = function (exports, require, module) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ParticleSystem = void 0;
class ParticleSystem {
    constructor() {
        this.trailParticles = null;
        this.debrisParticles = null;
        this.trailHead = 0;
        this.trailCapacity = 500;
        this.trailPositions = new Float32Array(this.trailCapacity * 3);
        this.debrisPositions = new Float32Array(200 * 3);
        this.debrisVelocities = new Array(200 * 3).fill(0);
        this.initDebris();
    }
    initDebris() {
        for (let i = 0; i < 200; i++) {
            this.debrisPositions[i * 3] = (Math.random() - 0.5) * 80;
            this.debrisPositions[i * 3 + 1] = (Math.random() - 0.5) * 50;
            this.debrisPositions[i * 3 + 2] = -Math.random() * 300;
        }
    }
    init(scene) {
        // Trail
        const trailGeo = new THREE.BufferGeometry();
        trailGeo.setAttribute('position', new THREE.BufferAttribute(this.trailPositions, 3));
        const trailMat = new THREE.PointsMaterial({
            color: 0xff6a00,
            size: 0.4,
            transparent: true,
            opacity: 0.6,
            blending: 1, // AdditiveBlending
            depthWrite: false,
        });
        this.trailParticles = new THREE.Points(trailGeo, trailMat);
        scene.add(this.trailParticles);
        // Debris
        const debrisGeo = new THREE.BufferGeometry();
        debrisGeo.setAttribute('position', new THREE.BufferAttribute(this.debrisPositions, 3));
        const debrisMat = new THREE.PointsMaterial({
            color: 0xffaa44,
            size: 0.2,
            transparent: true,
            opacity: 0.3,
            depthWrite: false,
        });
        this.debrisParticles = new THREE.Points(debrisGeo, debrisMat);
        scene.add(this.debrisParticles);
    }
    addTrailPoint(x, y, z) {
        const idx = this.trailHead * 3;
        this.trailPositions[idx] = x;
        this.trailPositions[idx + 1] = y;
        this.trailPositions[idx + 2] = z;
        this.trailHead = (this.trailHead + 1) % this.trailCapacity;
    }
    update(speed, dt) {
        if (this.debrisParticles) {
            const pos = this.debrisParticles.geometry.attributes.position.array;
            for (let i = 0; i < 200; i++) {
                pos[i * 3] += this.debrisVelocities[i * 3] * dt;
                pos[i * 3 + 1] += this.debrisVelocities[i * 3 + 1] * dt;
                pos[i * 3 + 2] += (speed * 2 + this.debrisVelocities[i * 3 + 2]) * dt;
                if (pos[i * 3 + 2] > 20) {
                    pos[i * 3] = (Math.random() - 0.5) * 80;
                    pos[i * 3 + 1] = (Math.random() - 0.5) * 50;
                    pos[i * 3 + 2] = -300;
                }
            }
            this.debrisParticles.geometry.attributes.position.needsUpdate = true;
        }
    }
    dispose() {
        this.trailParticles?.geometry.dispose();
        this.trailParticles?.material?.dispose();
        this.debrisParticles?.geometry.dispose();
        this.debrisParticles?.material?.dispose();
    }
}
exports.ParticleSystem = ParticleSystem;
};

// ── module: src/audio.ts ──
__mods["src/audio.ts"] = function (exports, require, module) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AudioEngine = void 0;
class AudioEngine {
    constructor() {
        this.ctx = null;
        this.masterGain = null;
        this.engineOsc = null;
        this.engineGain = null;
        this.initialized = false;
    }
    init() {
        this.ctx = new (window.AudioContext || window.webkitAudioContext)();
        this.masterGain = this.ctx.createGain();
        this.masterGain.gain.value = 0.3;
        this.masterGain.connect(this.ctx.destination);
        // Engine drone
        this.engineOsc = this.ctx.createOscillator();
        this.engineGain = this.ctx.createGain();
        this.engineOsc.type = 'sawtooth';
        this.engineOsc.frequency.value = 60;
        this.engineGain.gain.value = 0;
        this.engineOsc.connect(this.engineGain);
        this.engineGain.connect(this.masterGain);
        this.engineOsc.start();
        this.initialized = true;
    }
    updateEngine(speed, boosting) {
        if (!this.initialized || !this.engineOsc)
            return;
        const freq = 50 + speed * 2 + (boosting ? 40 : 0);
        this.engineOsc.frequency.setTargetAtTime(freq, this.ctx.currentTime, 0.1);
        const vol = 0.08 + (boosting ? 0.06 : 0);
        this.engineGain.gain.setTargetAtTime(vol, this.ctx.currentTime, 0.1);
    }
    playCollect() {
        if (!this.initialized || !this.ctx)
            return;
        const osc = this.ctx.createOscillator();
        const gain = this.ctx.createGain();
        osc.type = 'sine';
        osc.frequency.value = 880;
        osc.frequency.exponentialRampToValueAtTime(1760, this.ctx.currentTime + 0.1);
        gain.gain.value = 0.15;
        gain.gain.exponentialRampToValueAtTime(0.001, this.ctx.currentTime + 0.2);
        osc.connect(gain);
        gain.connect(this.masterGain);
        osc.start();
        osc.stop(this.ctx.currentTime + 0.2);
    }
    playNearMiss() {
        if (!this.initialized || !this.ctx)
            return;
        const osc = this.ctx.createOscillator();
        const gain = this.ctx.createGain();
        osc.type = 'triangle';
        osc.frequency.value = 200;
        osc.frequency.exponentialRampToValueAtTime(800, this.ctx.currentTime + 0.15);
        gain.gain.value = 0.12;
        gain.gain.exponentialRampToValueAtTime(0.001, this.ctx.currentTime + 0.3);
        osc.connect(gain);
        gain.connect(this.masterGain);
        osc.start();
        osc.stop(this.ctx.currentTime + 0.3);
    }
    playCrash() {
        if (!this.initialized || !this.ctx)
            return;
        // Noise burst for crash
        const bufferSize = this.ctx.sampleRate * 0.5;
        const buffer = this.ctx.createBuffer(1, bufferSize, this.ctx.sampleRate);
        const data = buffer.getChannelData(0);
        for (let i = 0; i < bufferSize; i++) {
            data[i] = (Math.random() * 2 - 1) * Math.exp(-i / (bufferSize * 0.1));
        }
        const noise = this.ctx.createBufferSource();
        noise.buffer = buffer;
        const gain = this.ctx.createGain();
        gain.gain.value = 0.3;
        gain.gain.exponentialRampToValueAtTime(0.001, this.ctx.currentTime + 0.5);
        noise.connect(gain);
        gain.connect(this.masterGain);
        noise.start();
        // Low thud
        const osc = this.ctx.createOscillator();
        const g2 = this.ctx.createGain();
        osc.type = 'sine';
        osc.frequency.value = 80;
        osc.frequency.exponentialRampToValueAtTime(20, this.ctx.currentTime + 0.5);
        g2.gain.value = 0.2;
        g2.gain.exponentialRampToValueAtTime(0.001, this.ctx.currentTime + 0.5);
        osc.connect(g2);
        g2.connect(this.masterGain);
        osc.start();
        osc.stop(this.ctx.currentTime + 0.5);
    }
}
exports.AudioEngine = AudioEngine;
};

// ── entry ──
__require("src/main.ts");
})();
</script>
</body>
</html>
<!-- agent-meta {"model":"ThinkingCap-Qwen3.6-27B-GGUF","provider":"brigid","persona":"typescript","sessionId":"b85c5838-0fcf-41af-8e73-9d485ed53eca","tokensIn":802252,"tokensOut":24967,"tokensTotal":827219,"cost":0,"turns":39,"toolCalls":45,"failedToolCalls":6,"timestamp":"2026-08-03T20:14:19.443Z"} -->