fun: generate a forest
This commit is contained in:
parent
10d6638452
commit
466e80aa23
147
app/create-forest.js
Normal file
147
app/create-forest.js
Normal 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;
|
||||
}
|
||||
|
|
@ -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: {},
|
||||
|
|
|
@ -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('/'),
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue
Block a user