Canyon Run
GPT 5.6 terra · typescript
◈Preview unavailable — try playing the result
Browser check: Preview unavailable or timed out. 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 17,780 bytes · SHA-256 04668e97523b
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>CANYON // OVERDRIVE</title>
<script src="https://cdn.jsdelivr.net/npm/three@0.160.0/build/three.min.js"></script>
<style>
/* ── css: layout ── */
*{box-sizing:border-box}html,body,#app,#game-shell{margin:0;width:100%;height:100%;overflow:hidden;background:#100c21;color:#fff;font-family:Arial,Helvetica,sans-serif}#game-shell{position:relative;isolation:isolate}canvas{width:100%;height:100%;display:block;cursor:crosshair}#vignette{pointer-events:none;position:absolute;inset:0;background:radial-gradient(ellipse at center,transparent 35%,rgba(5,3,15,.25) 68%,rgba(3,1,10,.8) 115%);mix-blend-mode:multiply;z-index:3}#hud{position:absolute;inset:0;pointer-events:none;padding:28px 34px;z-index:4;text-shadow:0 1px 5px #11061d}.topline{display:flex;justify-content:space-between;align-items:center;font-size:10px;letter-spacing:2.1px;color:#c8b5df}.brand{font-weight:bold;color:#fff;font-size:13px;letter-spacing:2.7px}.brand span{color:#ffb13b;margin:0 3px}#status{color:#ffb13b}.readout{position:absolute;left:34px;top:86px;width:165px}.readout span,.energy-head span{display:block;font-size:9px;letter-spacing:2px;color:#c6b1d5}.readout b{font-size:34px;font-weight:400;letter-spacing:-1px}.readout i{font-style:normal;font-size:9px;color:#ffb13b;margin-left:5px;letter-spacing:1px}.speed-line{height:2px;background:rgba(255,255,255,.2);margin-top:6px}.speed-line em{display:block;height:100%;width:50%;background:#ffb13b;box-shadow:0 0 12px #ff9b27}.center-readout{position:absolute;top:17%;left:50%;transform:translateX(-50%);text-align:center}.center-readout div:first-child{font-size:42px;font-weight:800;letter-spacing:-2px;color:#fff;text-shadow:0 0 18px rgba(255,183,77,.4)}#nearText{font-size:9px;letter-spacing:2.8px;color:#ffbf55;margin-top:1px}.energy{position:absolute;left:34px;bottom:60px;width:205px}.energy-head{display:flex;justify-content:space-between;align-items:center}.energy-head b{font-size:12px;color:#ffbe56}.energy-bar{margin-top:8px;height:5px;background:rgba(255,255,255,.12);border:1px solid rgba(255,255,255,.15)}.energy-bar i{height:100%;display:block;width:100%;background:linear-gradient(90deg,#ff632d,#ffc948);box-shadow:0 0 13px #ff852e}.telemetry{position:absolute;right:34px;bottom:35px;display:flex;gap:20px;font-size:9px;letter-spacing:1.5px;color:#b9a7cb}.telemetry b{color:#fff;font-size:11px}.controls{position:absolute;bottom:25px;left:50%;transform:translateX(-50%);font-size:9px;letter-spacing:1.7px;color:rgba(255,255,255,.5);white-space:nowrap}.overlay{z-index:6;position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;background:linear-gradient(rgba(13,7,28,.22),rgba(13,5,25,.48));transition:.45s}.overlay.hidden{opacity:0;pointer-events:none;transform:scale(1.04)}.eyebrow{color:#ffbd50;font-size:10px;letter-spacing:4px;margin-bottom:13px}.eyebrow.danger{color:#ff6148}h1{margin:0;color:#f6f0ff;font-size:clamp(48px,9vw,112px);line-height:.77;letter-spacing:-6px;font-weight:800}h1 strong{color:#ffae39;text-shadow:0 0 25px rgba(255,139,35,.25)}.overlay p{max-width:360px;font-size:13px;line-height:1.6;color:#d3c6df;margin:26px 0}button{border:1px solid #ffbd53;background:rgba(255,166,41,.12);color:#fff;padding:15px 24px;font:700 11px Arial;letter-spacing:2.3px;cursor:pointer;transition:.2s}button:hover{background:#ffad35;color:#1b1021;box-shadow:0 0 25px #ff9c31}button small{font-size:8px;opacity:.7;margin-left:7px}.results{display:flex;gap:45px;margin:29px 0}.results div{display:flex;flex-direction:column}.results span{font-size:9px;letter-spacing:2px;color:#c2afcf}.results b{font-size:21px;color:#fff;margin-top:5px}@media(max-width:600px){#hud{padding:18px}.readout{left:18px;top:62px}.energy{left:18px;bottom:47px}.telemetry{right:18px;bottom:21px}.controls{display:none}.topline #status{display:none}.center-readout{top:14%}}
</style>
</head>
<body>
<main id="game-shell"><canvas id="gameCanvas" aria-label="Canyon racer game"></canvas><section id="hud"><div class="topline"><div class="brand">CANYON<span>//</span>OVERDRIVE</div><div id="status">RUNNING · SECTOR 01</div></div><div class="readout speed"><span>VELOCITY</span><b id="speedVal">680</b><i>KM/H</i><div class="speed-line"><em id="speedFill"></em></div></div><div class="center-readout"><div id="multiplier">x1.0</div><div id="nearText">STAY SHARP</div></div><div class="energy"><div class="energy-head"><span>ENERGY CELL</span><b id="energyVal">100%</b></div><div class="energy-bar"><i id="energyFill"></i></div></div><div class="telemetry"><span>◈ ORBS <b id="orbs">00</b></span><span>◆ SCORE <b id="score">000000</b></span><span>▲ TURBO <b id="turbo">READY</b></span></div><div class="controls">← → / A D BANK · ↑ ↓ PITCH · SPACE BOOST</div></section><section id="intro" class="overlay"><div class="eyebrow">PROCEDURAL FLIGHT SYSTEM</div><h1>RIDE THE<br><strong>RIFT</strong></h1><p>Thread the canyon. Harvest solar cells. Let nothing touch your wings.</p><button id="startBtn">INITIATE RUN <small>[ ENTER ]</small></button></section><section id="gameover" class="overlay hidden"><div class="eyebrow danger">SIGNAL LOST</div><h1>RUN<br><strong>TERMINATED</strong></h1><div class="results"><div><span>FINAL SCORE</span><b id="finalScore">000000</b></div><div><span>MAX VELOCITY</span><b id="maxSpeed">000 KM/H</b></div></div><button id="restartBtn">RUN AGAIN <small>[ ENTER ]</small></button></section><div id="vignette"></div></main>
<script>
(function () {
'use strict';
var __mods = {};
var __cache = {};
var __map = {};
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 T = THREE;
const canvas = document.querySelector('#gameCanvas');
const $ = (s) => document.querySelector(s);
const ui = { speed: $('#speedVal'), speedFill: $('#speedFill'), multi: $('#multiplier'), near: $('#nearText'), energy: $('#energyVal'), energyFill: $('#energyFill'), score: $('#score'), orbs: $('#orbs'), turbo: $('#turbo'), intro: $('#intro'), over: $('#gameover'), final: $('#finalScore'), max: $('#maxSpeed'), start: $('#startBtn'), restart: $('#restartBtn') };
const renderer = new T.WebGLRenderer({ canvas, antialias: true, powerPreference: 'high-performance' });
renderer.setPixelRatio(Math.min(devicePixelRatio, 1.7));
renderer.setSize(innerWidth, innerHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = T.PCFSoftShadowMap;
renderer.toneMapping = T.ACESFilmicToneMapping;
renderer.toneMappingExposure = 1.2;
const scene = new T.Scene();
scene.background = new T.Color(0x160c2a);
scene.fog = new T.FogExp2(0x241035, .009);
const camera = new T.PerspectiveCamera(70, innerWidth / innerHeight, .1, 500);
camera.position.set(0, 3.1, 8);
const hemi = new T.HemisphereLight(0x9f79ff, 0x2b1124, 1.6);
scene.add(hemi);
const sun = new T.DirectionalLight(0xffa64c, 3.4);
sun.position.set(-20, 30, 10);
sun.castShadow = true;
sun.shadow.mapSize.set(1024, 1024);
scene.add(sun);
const world = new T.Group();
scene.add(world);
const matRock = new T.MeshStandardMaterial({ color: 0x4c2555, roughness: .86, flatShading: true });
const matRock2 = new T.MeshStandardMaterial({ color: 0x7b3653, roughness: .8, flatShading: true });
const matSilver = new T.MeshStandardMaterial({ color: 0x8f7ea3, roughness: .3, metalness: .76, flatShading: true });
const glowMat = new T.MeshBasicMaterial({ color: 0xffcf55 });
const ground = new T.Mesh(new T.PlaneGeometry(260, 1000), new T.MeshStandardMaterial({ color: 0x30153d, roughness: 1 }));
ground.rotation.x = -Math.PI / 2;
ground.position.y = -10;
ground.receiveShadow = true;
scene.add(ground);
// craft
const craft = new T.Group();
const body = new T.Mesh(new T.ConeGeometry(.48, 2.25, 4), matSilver);
body.rotation.x = Math.PI / 2;
body.scale.set(1, .42, 1);
body.castShadow = true;
craft.add(body);
const wingGeo = new T.ConeGeometry(.8, 1.9, 3);
const wing = new T.Mesh(wingGeo, new T.MeshStandardMaterial({ color: 0xff7d35, metalness: .35, roughness: .3, flatShading: true, emissive: 0x3b1008 }));
wing.rotation.set(Math.PI / 2, 0, Math.PI / 2);
wing.scale.set(1, .13, 1);
wing.position.set(0, -.1, .1);
craft.add(wing);
const engine = new T.PointLight(0xff6a2e, 4, 13);
engine.position.z = .9;
craft.add(engine);
craft.position.set(0, 0, 4);
scene.add(craft);
const chunks = [];
const obstacles = [];
const orbs = [];
const particles = [];
let running = false, dead = false, score = 0, energy = 100, speed = 50, maxSpeed = 0, multiplier = 1, orbCount = 0, turbo = 100, last = performance.now(), elapsed = 0;
let vx = 0, vy = 0, nearCooldown = 0;
let seed = 19;
const rand = () => { seed = (seed * 16807) % 2147483647; return (seed - 1) / 2147483646; };
function rock(x, y, z, sx, sy, sz, mat = matRock) { const m = new T.Mesh(new T.DodecahedronGeometry(1, 1), mat); m.position.set(x, y, z); m.scale.set(sx, sy, sz); m.rotation.set(rand() * 2, rand() * 2, rand() * 2); m.castShadow = true; m.receiveShadow = true; world.add(m); return m; }
function generate(z) { const g = new T.Group(); world.add(g); chunks.push({ z, g }); const difficulty = Math.min(1.8, 1 + score / 25000); for (let i = 0; i < 8; i++) {
let zz = z - i * 12;
const bend = Math.sin(zz * .034) * 3;
const gap = 5.5 - Math.min(1.8, difficulty * .55);
for (const side of [-1, 1]) {
const r = rock(bend + side * (gap + rand() * 2.5), -2 + rand() * 1.5, zz, 2 + rand() * 2, 7 + rand() * 5, 4 + rand() * 3, rand() > .5 ? matRock : matRock2);
g.add(r);
world.remove(r);
g.add(r);
}
if (rand() < .52) {
const x = bend + (rand() > .5 ? 1 : -1) * (gap - 1.0);
const m = rock(x, rand() * 4 - 1, zz - 3, 1.1, 5 + rand() * 3, 1.1, matSilver);
obstacles.push({ m, r: 1.25 });
g.add(m);
world.remove(m);
g.add(m);
}
if (rand() < .72) {
const x = bend + (rand() - .5) * (gap * 1.25);
const y = rand() * 3 - 1;
const o = new T.Mesh(new T.OctahedronGeometry(.34, 1), glowMat.clone());
o.position.set(x, y, zz);
const l = new T.PointLight(0xffbd3c, 2.2, 7);
o.add(l);
g.add(o);
orbs.push({ m: o, phase: rand() * 6 });
}
} }
for (let z = -20; z > -270; z -= 72)
generate(z);
for (let i = 0; i < 90; i++) {
const p = new T.Mesh(new T.TetrahedronGeometry(.035), new T.MeshBasicMaterial({ color: i % 3 ? 0xff9c4b : 0xc782ff }));
scene.add(p);
particles.push(p);
}
const keys = new Set();
addEventListener('keydown', e => { keys.add(e.code); if (e.code === 'Enter' && !running)
start(); if (e.code === 'Space')
e.preventDefault(); });
addEventListener('keyup', e => keys.delete(e.code));
let audio;
function sound(kind) { try {
const C = window.AudioContext;
audio ?? (audio = new C());
const o = audio.createOscillator(), g = audio.createGain();
o.connect(g);
g.connect(audio.destination);
o.type = kind === 'orb' ? 'sine' : kind === 'near' ? 'triangle' : 'sawtooth';
o.frequency.value = kind === 'orb' ? 780 : kind === 'near' ? 190 : 75;
g.gain.setValueAtTime(kind === 'near' ? .06 : .035, audio.currentTime);
g.gain.exponentialRampToValueAtTime(.001, audio.currentTime + .16);
o.start();
o.stop(audio.currentTime + .17);
}
catch { } }
function start() { running = true; dead = false; score = 0; energy = 100; speed = 52; maxSpeed = 0; multiplier = 1; orbCount = 0; turbo = 100; craft.position.set(0, 0, 4); vx = vy = 0; ui.intro.classList.add('hidden'); ui.over.classList.add('hidden'); sound('near'); }
function end() { running = false; dead = true; ui.final.textContent = Math.floor(score).toString().padStart(6, '0'); ui.max.textContent = Math.floor(maxSpeed * 12) + ' KM/H'; ui.over.classList.remove('hidden'); sound('near'); }
function resize() { renderer.setSize(innerWidth, innerHeight); camera.aspect = innerWidth / innerHeight; camera.updateProjectionMatrix(); }
addEventListener('resize', resize);
function frame(now) {
requestAnimationFrame(frame);
const dt = Math.min(.035, (now - last) / 1000);
last = now;
if (running) {
elapsed += dt;
const left = keys.has('ArrowLeft') || keys.has('KeyA'), right = keys.has('ArrowRight') || keys.has('KeyD'), up = keys.has('ArrowUp') || keys.has('KeyW'), down = keys.has('ArrowDown') || keys.has('KeyS'), boost = keys.has('Space') && turbo > 1;
vx += (right ? 1 : 0) * 18 * dt - (left ? 1 : 0) * 18 * dt;
vy += (up ? 1 : 0) * 13 * dt - (down ? 1 : 0) * 13 * dt;
vx *= .91;
vy *= .91;
craft.position.x += vx * dt;
craft.position.y += vy * dt;
craft.position.x = T.MathUtils.clamp(craft.position.x, -7.7, 7.7);
craft.position.y = T.MathUtils.clamp(craft.position.y, -5.2, 5.5);
const target = 54 + Math.min(38, score / 9000) + (boost ? 32 : 0);
speed += (target - speed) * dt * (boost ? 3.5 : 1.3);
if (boost)
turbo -= 28 * dt;
else
turbo = Math.min(100, turbo + 4 * dt);
energy -= dt * (1.2 + speed * .009);
score += speed * dt * multiplier * 2.4;
maxSpeed = Math.max(maxSpeed, speed);
craft.rotation.z = T.MathUtils.lerp(craft.rotation.z, -vx * .11, .12);
craft.rotation.x = T.MathUtils.lerp(craft.rotation.x, vy * .06, .1);
craft.position.z = 4;
world.position.z += speed * dt;
ground.position.z = world.position.z;
camera.fov = T.MathUtils.lerp(camera.fov, boost ? 88 : 70, .07);
camera.updateProjectionMatrix();
camera.position.x = T.MathUtils.lerp(camera.position.x, craft.position.x * .24, .07);
camera.position.y = T.MathUtils.lerp(camera.position.y, 3.0 + craft.position.y * .16, .07);
camera.rotation.z = -craft.rotation.z * .12;
while (chunks.length && chunks[0].z + world.position.z > 35) {
const old = chunks.shift();
old.g.traverse((o) => { if (o.geometry)
o.geometry.dispose(); });
world.remove(old.g);
}
const far = chunks.length ? chunks[chunks.length - 1].z : -260;
if (far + world.position.z > -260)
generate(far - 72);
for (let i = obstacles.length - 1; i >= 0; i--) {
const q = obstacles[i], p = q.m.getWorldPosition(new T.Vector3());
if (p.z > 15) {
obstacles.splice(i, 1);
continue;
}
const d = Math.hypot(p.x - craft.position.x, p.y - craft.position.y, p.z - craft.position.z);
if (d < 1.05) {
end();
}
else if (d < 2.35 && nearCooldown <= 0) {
multiplier = Math.min(8, multiplier + .25);
nearCooldown = .5;
score += 120 * multiplier;
ui.near.textContent = 'NEAR MISS // +' + multiplier.toFixed(2);
sound('near');
}
}
nearCooldown -= dt;
for (let i = orbs.length - 1; i >= 0; i--) {
const q = orbs[i], p = q.m.getWorldPosition(new T.Vector3());
q.m.rotation.y += dt * 3;
q.m.position.y += Math.sin(elapsed * 3 + q.phase) * dt * .3;
if (p.z > 17) {
orbs.splice(i, 1);
continue;
}
if (p.distanceTo(craft.position) < 1.1) {
energy = Math.min(100, energy + 24);
turbo = Math.min(100, turbo + 18);
orbCount++;
score += 250;
q.m.parent?.remove(q.m);
orbs.splice(i, 1);
sound('orb');
}
}
for (const p of particles) {
p.position.z += speed * dt * 1.6;
if (p.position.z > 8) {
p.position.set(craft.position.x + (rand() - .5) * 22, craft.position.y + (rand() - .5) * 13, -110 - rand() * 100);
}
p.rotation.x += dt * 4;
}
if (energy <= 0)
end();
ui.speed.textContent = Math.floor(speed * 12).toString();
ui.speedFill.style.width = Math.min(100, speed / 90 * 100) + '%';
ui.energy.textContent = Math.max(0, Math.floor(energy)) + '%';
ui.energyFill.style.width = Math.max(0, energy) + '%';
ui.score.textContent = Math.floor(score).toString().padStart(6, '0');
ui.orbs.textContent = orbCount.toString().padStart(2, '0');
ui.multi.textContent = 'x' + multiplier.toFixed(2);
ui.turbo.textContent = turbo > 70 ? 'READY' : Math.floor(turbo) + '%';
}
renderer.render(scene, camera);
}
requestAnimationFrame(frame);
ui.start.addEventListener('click', start);
ui.restart.addEventListener('click', start);
};
// ── types: globals.d.ts ──
__mods["globals.d.ts"] = function (exports) {};
// ── entry ──
__require("src/main.ts");
})();
</script>
</body>
</html>
<!-- agent-meta {"model":"openai/gpt-5.6-terra","provider":"openrouter","persona":"typescript","sessionId":"ca935fd5-42cb-46bd-b48e-bec9f505b3ce","tokensIn":133251,"tokensOut":5897,"tokensTotal":139148,"turns":15,"toolCalls":17,"failedToolCalls":1,"timestamp":"2026-07-31T16:26:38.654Z"} -->