fun: generate a forest

This commit is contained in:
cha0s 2024-07-10 14:59:07 -05:00
parent 10d6638452
commit 466e80aa23
4 changed files with 167 additions and 1 deletions

147
app/create-forest.js Normal file
View File

@ -0,0 +1,147 @@
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;
}

View File

@ -15,7 +15,7 @@ export default async function createPlayer(id) {
},
Controlled: {},
Direction: {direction: 2},
Ecs: {path: ['homesteads', `${id}`].join('/')},
Ecs: {path: ['forests', `${id}`].join('/')},
Emitter: {},
Forces: {},
Interacts: {},

View File

@ -7,6 +7,7 @@ import {decode, encode} from '@/packets/index.js';
import Script from '@/util/script.js';
import createEcs from './create-ecs.js';
import createForest from './create-forest.js';
import createHomestead from './create-homestead.js';
import createHouse from './create-house.js';
import createPlayer from './create-player.js';
@ -260,6 +261,11 @@ export default class Engine {
['houses', `${id}`].join('/'),
house,
);
const forest = await createForest(this.Ecs, id);
await this.saveEcs(
['forests', `${id}`].join('/'),
forest,
);
buffer = await createPlayer(id);
await this.server.writeData(
['players', `${id}`].join('/'),

View File

@ -2,6 +2,7 @@ import {del, get, set} from 'idb-keyval';
import {encode} from '@/packets/index.js';
import '../../create-forest.js';
import '../../create-homestead.js';
import '../../create-player.js';
@ -92,6 +93,18 @@ if (import.meta.hot) {
// await engine.server.writeData('players/0', (new TextEncoder()).encode(JSON.stringify(player)));
resolver.resolve();
});
import.meta.hot.accept('../../create-forest.js', async ({default: createForest}) => {
const resolver = createResolver();
resolvers.push(resolver);
await beforeResolver;
delete engine.ecses['forests/0'];
await engine.server.removeData('forests/0');
const last = performance.now();
const forest = await createForest(engine.Ecs, '0');
console.log((performance.now() - last) / 1000);
await engine.saveEcs('forests/0', forest);
resolver.resolve();
});
import.meta.hot.accept('../../create-homestead.js', async ({default: createHomestead}) => {
const resolver = createResolver();
resolvers.push(resolver);