50 lines
1.6 KiB
TypeScript
50 lines
1.6 KiB
TypeScript
import { MAT_FOOD, MAT_HOME, MAT_SAND } from "./constants";
|
|
|
|
// simple seeded PRNG for deterministic placement
|
|
function mulberry32(seed: number) {
|
|
return () => {
|
|
seed += 0x6d2b79f5;
|
|
let t = seed;
|
|
t = Math.imul(t ^ (t >>> 15), t | 1);
|
|
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
|
|
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
|
|
};
|
|
}
|
|
|
|
export function generateSideViewWorld(
|
|
worldSize: number,
|
|
seed: boolean,
|
|
): Float32Array {
|
|
const data = new Float32Array(worldSize * worldSize * 4);
|
|
const sandHeight = Math.floor(worldSize * 0.6);
|
|
const surfaceRow = sandHeight - 1;
|
|
|
|
// fill bottom 60% with sand
|
|
for (let y = 0; y < sandHeight; y++) {
|
|
for (let x = 0; x < worldSize; x++) {
|
|
const idx = (y * worldSize + x) * 4;
|
|
data[idx] = MAT_SAND;
|
|
}
|
|
}
|
|
// top 40% stays MAT_AIR (Float32Array is zero-initialized)
|
|
|
|
if (seed) {
|
|
const rng = mulberry32(Date.now());
|
|
// place home at random surface position (middle 60% of world width)
|
|
const margin = Math.floor(worldSize * 0.2);
|
|
const homeX = margin + Math.floor(rng() * (worldSize - 2 * margin));
|
|
|
|
const homeIdx = (surfaceRow * worldSize + homeX) * 4;
|
|
data[homeIdx] = MAT_HOME;
|
|
|
|
// place food at a different random surface position
|
|
let foodX = homeX;
|
|
while (foodX === homeX) {
|
|
foodX = margin + Math.floor(rng() * (worldSize - 2 * margin));
|
|
}
|
|
const foodIdx = (surfaceRow * worldSize + foodX) * 4;
|
|
data[foodIdx] = MAT_FOOD;
|
|
}
|
|
|
|
return data;
|
|
}
|