Files
blackroad-metaverse/infinite-biomes.js
Alexa Louise 4139f10660 ULTIMATE BLACKROAD METAVERSE - Complete Integration
Complete infinite 3D universe with all systems integrated:

Features:
- Particle effects (rain, snow, fireflies with physics)
- Day/night cycle (dynamic sun, sky colors, time display)
- Infinite biome generation (6 biomes, chunk loading)
- Transportation system (teleport, flying, fast travel)
- Living AI agents (Alice, Aria, Lucidia in 3D)
- Perlin noise terrain (procedural, deterministic)
- Glass morphism UI (modern, beautiful)

Technical:
- Single 40KB HTML file with entire metaverse
- Three.js r160 + WebGL 2.0
- 60 FPS target performance
- Up to 3,100 particles active
- ~25 chunks loaded in view
- Custom Perlin noise implementation

Controls:
- WASD + Mouse - Move and look
- F - Toggle flying
- T - Teleport menu
- R/N/G - Rain/Snow/Fireflies

Live: https://ba23b228.blackroad-metaverse.pages.dev

Built with 💚 for infinite exploration and freedom

🌌 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-21 21:52:46 -06:00

481 lines
14 KiB
JavaScript

/**
* INFINITE BIOME GENERATION
*
* Procedurally generates never-ending beautiful landscapes:
* - Forests with trees and flowers
* - Oceans with waves
* - Mountains with snow
* - Deserts with dunes
* - Crystal caverns
* - Floating islands
* - And infinite more...
*/
import * as THREE from 'three';
/**
* PERLIN NOISE
* For natural terrain generation
*/
class PerlinNoise {
constructor(seed = Math.random()) {
this.grad3 = [[1,1,0],[-1,1,0],[1,-1,0],[-1,-1,0],
[1,0,1],[-1,0,1],[1,0,-1],[-1,0,-1],
[0,1,1],[0,-1,1],[0,1,-1],[0,-1,-1]];
this.p = [];
for(let i=0; i<256; i++) {
this.p[i] = Math.floor(Math.random() * 256);
}
this.perm = [];
for(let i=0; i<512; i++) {
this.perm[i] = this.p[i & 255];
}
}
dot(g, x, y, z) {
return g[0]*x + g[1]*y + g[2]*z;
}
mix(a, b, t) {
return (1-t)*a + t*b;
}
fade(t) {
return t*t*t*(t*(t*6-15)+10);
}
noise(x, y, z) {
let X = Math.floor(x) & 255;
let Y = Math.floor(y) & 255;
let Z = Math.floor(z) & 255;
x -= Math.floor(x);
y -= Math.floor(y);
z -= Math.floor(z);
let u = this.fade(x);
let v = this.fade(y);
let w = this.fade(z);
let A = this.perm[X ]+Y, AA = this.perm[A]+Z, AB = this.perm[A+1]+Z;
let B = this.perm[X+1]+Y, BA = this.perm[B]+Z, BB = this.perm[B+1]+Z;
return this.mix(
this.mix(
this.mix(this.dot(this.grad3[this.perm[AA ]%12], x, y, z),
this.dot(this.grad3[this.perm[BA ]%12], x-1, y, z), u),
this.mix(this.dot(this.grad3[this.perm[AB ]%12], x, y-1, z),
this.dot(this.grad3[this.perm[BB ]%12], x-1, y-1, z), u), v),
this.mix(
this.mix(this.dot(this.grad3[this.perm[AA+1]%12], x, y, z-1),
this.dot(this.grad3[this.perm[BA+1]%12], x-1, y, z-1), u),
this.mix(this.dot(this.grad3[this.perm[AB+1]%12], x, y-1, z-1),
this.dot(this.grad3[this.perm[BB+1]%12], x-1, y-1, z-1), u), v), w);
}
}
/**
* BIOME TYPES
*/
export const BIOMES = {
FOREST: {
name: 'Enchanted Forest',
colors: {
ground: 0x2d5016,
plants: 0x4CAF50,
flowers: [0xFF6B9D, 0xFFD700, 0x9B59B6, 0x4A90E2],
sky: 0x87CEEB
},
features: ['trees', 'flowers', 'mushrooms', 'fireflies'],
density: 0.3,
heightVariation: 5
},
OCEAN: {
name: 'Infinite Ocean',
colors: {
water: 0x006994,
foam: 0xffffff,
sky: 0x87CEEB
},
features: ['waves', 'coral', 'fish', 'seaweed'],
density: 0.1,
heightVariation: 2
},
MOUNTAIN: {
name: 'Crystalline Peaks',
colors: {
rock: 0x8B7355,
snow: 0xFFFAFA,
crystal: 0x9B59B6,
sky: 0xB0E0E6
},
features: ['peaks', 'snow', 'crystals', 'ice'],
density: 0.2,
heightVariation: 50
},
DESERT: {
name: 'Golden Dunes',
colors: {
sand: 0xF4A460,
rock: 0x8B7355,
sky: 0xFFA500
},
features: ['dunes', 'cacti', 'rocks', 'mirages'],
density: 0.05,
heightVariation: 10
},
CRYSTAL: {
name: 'Crystal Caverns',
colors: {
crystal: [0x9B59B6, 0x4A90E2, 0xE74C3C, 0x27AE60],
glow: 0xFFFFFF,
ground: 0x2C3E50
},
features: ['giant_crystals', 'glowing_ore', 'gems', 'light_beams'],
density: 0.4,
heightVariation: 15
},
FLOATING: {
name: 'Sky Islands',
colors: {
grass: 0x7CFC00,
stone: 0x708090,
sky: 0xE0F6FF,
clouds: 0xFFFFFF
},
features: ['floating_islands', 'waterfalls', 'clouds', 'birds'],
density: 0.15,
heightVariation: 30
}
};
/**
* INFINITE BIOME GENERATOR
*/
export class InfiniteBiomeGenerator {
constructor(scene) {
this.scene = scene;
this.noise = new PerlinNoise();
this.chunks = new Map();
this.chunkSize = 50;
this.renderDistance = 5; // chunks
this.currentChunk = { x: 0, z: 0 };
}
/**
* Get biome at world position
*/
getBiomeAt(x, z) {
// Use noise to determine biome
const biomeNoise = this.noise.noise(x * 0.01, 0, z * 0.01);
const moistureNoise = this.noise.noise(x * 0.02, 100, z * 0.02);
if (biomeNoise > 0.6) return BIOMES.MOUNTAIN;
if (biomeNoise < -0.3) return BIOMES.OCEAN;
if (moistureNoise > 0.3) return BIOMES.FOREST;
if (moistureNoise < -0.3) return BIOMES.DESERT;
if (Math.abs(biomeNoise) < 0.1 && Math.abs(moistureNoise) < 0.1) return BIOMES.CRYSTAL;
if (biomeNoise > 0.4 && moistureNoise > 0) return BIOMES.FLOATING;
return BIOMES.FOREST; // Default
}
/**
* Generate terrain chunk
*/
generateChunk(chunkX, chunkZ) {
const chunkKey = `${chunkX},${chunkZ}`;
if (this.chunks.has(chunkKey)) return this.chunks.get(chunkKey);
const chunk = new THREE.Group();
chunk.name = chunkKey;
const startX = chunkX * this.chunkSize;
const startZ = chunkZ * this.chunkSize;
// Generate terrain mesh
const resolution = 32;
const geometry = new THREE.PlaneGeometry(
this.chunkSize,
this.chunkSize,
resolution - 1,
resolution - 1
);
const vertices = geometry.attributes.position.array;
const biome = this.getBiomeAt(startX + this.chunkSize/2, startZ + this.chunkSize/2);
// Heightmap
for (let i = 0; i < vertices.length; i += 3) {
const x = vertices[i] + startX;
const z = vertices[i + 1] + startZ;
// Multi-octave noise for natural terrain
let height = 0;
height += this.noise.noise(x * 0.02, 0, z * 0.02) * 10;
height += this.noise.noise(x * 0.05, 1, z * 0.05) * 5;
height += this.noise.noise(x * 0.1, 2, z * 0.1) * 2;
vertices[i + 2] = height * (biome.heightVariation / 10);
}
geometry.attributes.position.needsUpdate = true;
geometry.computeVertexNormals();
// Material based on biome
const material = new THREE.MeshStandardMaterial({
color: biome.colors.ground || biome.colors.grass || 0x4CAF50,
roughness: 0.8,
metalness: 0.2
});
const terrain = new THREE.Mesh(geometry, material);
terrain.rotation.x = -Math.PI / 2;
terrain.position.set(startX + this.chunkSize/2, 0, startZ + this.chunkSize/2);
chunk.add(terrain);
// Add biome features
this.addBiomeFeatures(chunk, startX, startZ, biome);
chunk.position.set(0, 0, 0);
this.scene.add(chunk);
this.chunks.set(chunkKey, chunk);
return chunk;
}
/**
* Add beautiful features to biome
*/
addBiomeFeatures(chunk, startX, startZ, biome) {
const features = biome.features;
// Trees
if (features.includes('trees')) {
for (let i = 0; i < 20; i++) {
const x = startX + Math.random() * this.chunkSize;
const z = startZ + Math.random() * this.chunkSize;
const y = this.getHeightAt(x, z);
this.createTree(chunk, x, y, z, biome);
}
}
// Flowers
if (features.includes('flowers')) {
for (let i = 0; i < 50; i++) {
const x = startX + Math.random() * this.chunkSize;
const z = startZ + Math.random() * this.chunkSize;
const y = this.getHeightAt(x, z);
this.createFlower(chunk, x, y, z, biome);
}
}
// Crystals
if (features.includes('giant_crystals')) {
for (let i = 0; i < 10; i++) {
const x = startX + Math.random() * this.chunkSize;
const z = startZ + Math.random() * this.chunkSize;
const y = this.getHeightAt(x, z);
this.createCrystal(chunk, x, y, z, biome);
}
}
// Floating islands
if (features.includes('floating_islands')) {
for (let i = 0; i < 3; i++) {
const x = startX + Math.random() * this.chunkSize;
const z = startZ + Math.random() * this.chunkSize;
const y = 20 + Math.random() * 30;
this.createFloatingIsland(chunk, x, y, z);
}
}
}
/**
* Create beautiful tree
*/
createTree(chunk, x, y, z, biome) {
const tree = new THREE.Group();
// Trunk
const trunk = new THREE.Mesh(
new THREE.CylinderGeometry(0.3, 0.5, 5, 8),
new THREE.MeshStandardMaterial({ color: 0x8B4513 })
);
trunk.position.y = 2.5;
tree.add(trunk);
// Foliage
const foliage = new THREE.Mesh(
new THREE.SphereGeometry(3, 8, 8),
new THREE.MeshStandardMaterial({
color: biome.colors.plants,
roughness: 0.9
})
);
foliage.position.y = 6;
tree.add(foliage);
tree.position.set(x, y, z);
chunk.add(tree);
}
/**
* Create beautiful flower
*/
createFlower(chunk, x, y, z, biome) {
const flower = new THREE.Group();
// Stem
const stem = new THREE.Mesh(
new THREE.CylinderGeometry(0.02, 0.02, 0.5, 4),
new THREE.MeshStandardMaterial({ color: 0x228B22 })
);
stem.position.y = 0.25;
flower.add(stem);
// Petals
const colors = biome.colors.flowers || [0xFF69B4];
const petalColor = colors[Math.floor(Math.random() * colors.length)];
for (let i = 0; i < 6; i++) {
const petal = new THREE.Mesh(
new THREE.CircleGeometry(0.2, 16),
new THREE.MeshStandardMaterial({
color: petalColor,
side: THREE.DoubleSide
})
);
const angle = (i / 6) * Math.PI * 2;
petal.position.set(
Math.cos(angle) * 0.2,
0.5,
Math.sin(angle) * 0.2
);
petal.rotation.y = angle;
flower.add(petal);
}
// Center
const center = new THREE.Mesh(
new THREE.SphereGeometry(0.1, 8, 8),
new THREE.MeshStandardMaterial({ color: 0xFFD700 })
);
center.position.y = 0.5;
flower.add(center);
flower.position.set(x, y, z);
chunk.add(flower);
}
/**
* Create glowing crystal
*/
createCrystal(chunk, x, y, z, biome) {
const height = 3 + Math.random() * 5;
const colors = biome.colors.crystal;
const color = Array.isArray(colors)
? colors[Math.floor(Math.random() * colors.length)]
: colors;
const crystal = new THREE.Mesh(
new THREE.ConeGeometry(0.5, height, 6),
new THREE.MeshStandardMaterial({
color: color,
emissive: color,
emissiveIntensity: 0.5,
metalness: 0.8,
roughness: 0.2,
transparent: true,
opacity: 0.8
})
);
crystal.position.set(x, y + height/2, z);
crystal.rotation.y = Math.random() * Math.PI;
// Add point light
const light = new THREE.PointLight(color, 2, 10);
light.position.set(x, y + height, z);
chunk.add(light);
chunk.add(crystal);
}
/**
* Create floating island
*/
createFloatingIsland(chunk, x, y, z) {
const island = new THREE.Group();
// Base
const base = new THREE.Mesh(
new THREE.SphereGeometry(5, 16, 16, 0, Math.PI * 2, 0, Math.PI / 2),
new THREE.MeshStandardMaterial({ color: 0x8B7355 })
);
island.add(base);
// Grass top
const grass = new THREE.Mesh(
new THREE.CircleGeometry(5, 32),
new THREE.MeshStandardMaterial({ color: 0x7CFC00 })
);
grass.rotation.x = -Math.PI / 2;
island.add(grass);
// Waterfall
const water = new THREE.Mesh(
new THREE.CylinderGeometry(0.5, 0.5, y, 8, 1, true),
new THREE.MeshStandardMaterial({
color: 0x4A90E2,
transparent: true,
opacity: 0.6
})
);
water.position.set(4, -y/2, 0);
island.add(water);
island.position.set(x, y, z);
chunk.add(island);
}
/**
* Get terrain height at position
*/
getHeightAt(x, z) {
let height = 0;
height += this.noise.noise(x * 0.02, 0, z * 0.02) * 10;
height += this.noise.noise(x * 0.05, 1, z * 0.05) * 5;
height += this.noise.noise(x * 0.1, 2, z * 0.1) * 2;
return height;
}
/**
* Update chunks based on player position
*/
update(playerX, playerZ) {
const chunkX = Math.floor(playerX / this.chunkSize);
const chunkZ = Math.floor(playerZ / this.chunkSize);
// Generate new chunks in render distance
for (let x = chunkX - this.renderDistance; x <= chunkX + this.renderDistance; x++) {
for (let z = chunkZ - this.renderDistance; z <= chunkZ + this.renderDistance; z++) {
this.generateChunk(x, z);
}
}
// Unload distant chunks
for (const [key, chunk] of this.chunks.entries()) {
const [cx, cz] = key.split(',').map(Number);
const distance = Math.max(Math.abs(cx - chunkX), Math.abs(cz - chunkZ));
if (distance > this.renderDistance + 2) {
this.scene.remove(chunk);
this.chunks.delete(key);
}
}
}
}
export default InfiniteBiomeGenerator;