Canyon Run
lfm2 24b a2b · basic

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