// Perlin Noise Generator // Implementacija za proceduralno generacijo terena class PerlinNoise { constructor(seed = Math.random()) { this.seed = seed; this.permutation = this.generatePermutation(); } generatePermutation() { const p = []; for (let i = 0; i < 256; i++) { p[i] = i; } // Fisher-Yates shuffle z seed-om let random = this.seed; for (let i = 255; i > 0; i--) { random = (random * 9301 + 49297) % 233280; const j = Math.floor((random / 233280) * (i + 1)); [p[i], p[j]] = [p[j], p[i]]; } // Podvoji permutacijo return [...p, ...p]; } fade(t) { return t * t * t * (t * (t * 6 - 15) + 10); } lerp(t, a, b) { return a + t * (b - a); } grad(hash, x, y) { const h = hash & 3; const u = h < 2 ? x : y; const v = h < 2 ? y : x; return ((h & 1) === 0 ? u : -u) + ((h & 2) === 0 ? v : -v); } noise(x, y) { const X = Math.floor(x) & 255; const Y = Math.floor(y) & 255; x -= Math.floor(x); y -= Math.floor(y); const u = this.fade(x); const v = this.fade(y); const p = this.permutation; const a = p[X] + Y; const aa = p[a]; const ab = p[a + 1]; const b = p[X + 1] + Y; const ba = p[b]; const bb = p[b + 1]; return this.lerp(v, this.lerp(u, this.grad(p[aa], x, y), this.grad(p[ba], x - 1, y)), this.lerp(u, this.grad(p[ab], x, y - 1), this.grad(p[bb], x - 1, y - 1)) ); } // Octave noise za bolj kompleksne terene octaveNoise(x, y, octaves = 4, persistence = 0.5) { let total = 0; let frequency = 1; let amplitude = 1; let maxValue = 0; for (let i = 0; i < octaves; i++) { total += this.noise(x * frequency, y * frequency) * amplitude; maxValue += amplitude; amplitude *= persistence; frequency *= 2; } return total / maxValue; } // Generira normalizirano vrednost med 0 in 1 getNormalized(x, y, scale = 0.1, octaves = 4) { const value = this.octaveNoise(x * scale, y * scale, octaves); return (value + 1) / 2; // Normalizacija iz [-1, 1] v [0, 1] } }