148 lines
3.7 KiB
JavaScript
148 lines
3.7 KiB
JavaScript
import alea from 'alea';
|
|
import {createNoise2D} from 'simplex-noise';
|
|
|
|
import {createRandom, Generator} from '@/util/math.js';
|
|
|
|
import createEcs from './create-ecs.js';
|
|
|
|
const seed = 42069;
|
|
const prng = alea(seed);
|
|
const rawNoise = createNoise2D(prng);
|
|
const noise = (x, y) => (1 + rawNoise(x, y)) / 2;
|
|
const random = createRandom(seed);
|
|
|
|
const indexComputer = (indices, randomizer) => (
|
|
(position) => indices[Math.floor(indices.length * randomizer(position))]
|
|
);
|
|
|
|
const [w, h] = [256, 256];
|
|
|
|
const Forest = new Generator({
|
|
calculate: indexComputer(
|
|
[1, 3, 4, 10, 11, 12], // grass
|
|
({x, y}) => noise(x * 30, y * 30),
|
|
),
|
|
covers: () => true,
|
|
size: {w, h},
|
|
children: [
|
|
new Generator({
|
|
calculate: indexComputer(
|
|
[342, 456], // dirt
|
|
({x, y}) => noise(x * 30, y * 30),
|
|
),
|
|
covers: ({x, y}) => noise(x * (1 / 16), y * (1 / 16)) < 0.5,
|
|
size: {w, h},
|
|
children: [
|
|
new Generator({
|
|
calculate: indexComputer(
|
|
[407, 408, 423, 424], // stone path
|
|
({x, y}) => noise(x * 30, y * 30),
|
|
),
|
|
covers: ({x, y}) => noise(x * (1 / 16), y * (1 / 16)) < 0.1625,
|
|
size: {w, h},
|
|
}),
|
|
],
|
|
}),
|
|
new Generator({
|
|
calculate: indexComputer(
|
|
[103, 104], // water
|
|
({x, y}) => noise(x * 30, y * 30),
|
|
),
|
|
covers: ({x, y}) => noise(x * (1 / 32), y * (1 / 32)) < 0.3,
|
|
size: {w, h},
|
|
}),
|
|
],
|
|
});
|
|
|
|
export default async function createForest(Ecs) {
|
|
const ecs = createEcs(Ecs);
|
|
const area = {x: w, y: h};
|
|
const master = ecs.get(await ecs.create({
|
|
AreaSize: {x: area.x * 16, y: area.y * 16},
|
|
Ticking: {},
|
|
TileLayers: {
|
|
layers: [
|
|
{
|
|
area,
|
|
data: Array(w * h).fill(0),
|
|
source: '/assets/tileset.json',
|
|
tileSize: {x: 16, y: 16},
|
|
},
|
|
{
|
|
area,
|
|
data: Array(w * h).fill(0),
|
|
source: '/assets/tileset.json',
|
|
tileSize: {x: 16, y: 16},
|
|
},
|
|
],
|
|
},
|
|
Time: {},
|
|
}));
|
|
Forest.generate();
|
|
const layer0 = master.TileLayers.layers[0];
|
|
layer0.data = Forest.matrix;
|
|
for (let y = 0; y < h; ++y) {
|
|
for (let x = 0; x < w; ++x) {
|
|
const dirt = Forest.children[0].matrix[y * w + x];
|
|
if (dirt) {
|
|
layer0.data[y * w + x] = dirt;
|
|
}
|
|
const stone = Forest.children[0].children[0].matrix[y * w + x];
|
|
if (stone) {
|
|
layer0.data[y * w + x] = stone;
|
|
}
|
|
const water = Forest.children[1].matrix[y * w + x];
|
|
if (water) {
|
|
layer0.data[y * w + x] = water;
|
|
}
|
|
}
|
|
}
|
|
|
|
const entityPosition = (x, y) => ({
|
|
x: (8 + (x * 16) + random() * 8 - 4),
|
|
y: (8 + (y * 16) + random() * 8 - 4),
|
|
});
|
|
|
|
for (let y = 0; y < h; ++y) {
|
|
for (let x = 0; x < w; ++x) {
|
|
let v = noise(x * (1 / 24), y * (1 / 24));
|
|
if (v > 0.2) {
|
|
v = noise(x * (1 / 7), y * (1 / 7));
|
|
if (v < 0.15) {
|
|
await ecs.create({
|
|
Position: entityPosition(x, y),
|
|
Sprite: {
|
|
anchorY: 0.7,
|
|
source: '/assets/ambient/shrub.json',
|
|
},
|
|
VisibleAabb: {},
|
|
});
|
|
}
|
|
else if (v < 0.17) {
|
|
await ecs.create({
|
|
Position: entityPosition(x, y),
|
|
Sprite: {
|
|
anchorY: 0.875,
|
|
source: '/assets/ambient/tree.json',
|
|
},
|
|
VisibleAabb: {},
|
|
});
|
|
}
|
|
v = noise(x * (1 / 12), y * (1 / 12));
|
|
if (v < 0.08) {
|
|
await ecs.create({
|
|
Position: entityPosition(x, y),
|
|
Sprite: {
|
|
anchorY: 0.7,
|
|
source: '/assets/ambient/flower.json',
|
|
},
|
|
VisibleAabb: {},
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ecs;
|
|
}
|
|
|