Canyon Run
Gemma 4 31b it · basic

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"} -->