dev: initial gen ui

This commit is contained in:
cha0s 2024-09-17 01:01:20 -05:00
parent 9853edec44
commit cd8a933a5b

186
app/routes/gen/route.jsx Normal file
View File

@ -0,0 +1,186 @@
import {Container, Sprite, Stage} from '@pixi/react';
import {useState} from 'react';
import TileLayer from '@/react/components/pixi/tile-layer.jsx';
import AssetsContext from '@/react/context/assets.js';
import {CHUNK_SIZE} from '@/util/constants.js';
import alea from 'alea';
import {createNoise2D} from 'simplex-noise';
// const seed = 3;
const dirt = [342, 456];
const grass = [1, 3, 4, 10, 11, 12];
// const stone = [407, 408, 423, 424];
// const water = [103, 104];
class Generator {
constructor({
area,
passes,
seed,
}) {
const prng = alea(seed);
const rawNoise = createNoise2D(prng);
this.noise = (x, y) => (1 + rawNoise(x, y)) / 2;
this.area = area;
this.passes = passes;
}
generate(fn) {
for (let y = 0; y < this.area.y; ++y) {
for (let x = 0; x < this.area.x; ++x) {
for (let j = this.passes.length - 1; j >=0; --j) {
if (this.passes[j].test(x, y, this.noise)) {
fn(this.passes[j].compute(x, y, this.noise), x, y);
break;
}
}
}
}
}
}
function Gen() {
const area = {x: 80, y: 80};
const assetsTuple = useState({});
const [seed, setSeed] = useState(0);
const [dirtClump, setDirtClump] = useState(30);
const [dirtPer, setDirtPer] = useState(0.3);
const dirtCheck = (x, y, noise) => noise(x / dirtClump, y / dirtClump) < dirtPer;
const tilePasses = [
{
test: () => 1,
compute: (x, y, noise) => grass[Math.floor(noise(x, y) * grass.length)],
},
{
test: dirtCheck,
compute: (x, y, noise) => dirt[Math.floor(noise(x, y) * dirt.length)],
},
{
test: (x, y, noise) => noise(x / 60, y / 60) < 0.25,
compute: () => 103,
},
{
test: (x, y, noise) => noise(x / 60, y / 60) < 0.14,
compute: () => 104,
},
];
const entityPasses = [
{
test: (x, y, noise) => (
dirtCheck(x, y, noise)
&& !(noise(x / 60, y / 60) < 0.25)
&& noise(x, y) < 0.2
),
compute: (x, y) => ({
anchor:{x: 0.5, y: 0.875},
image: '/assets/ambient/tree.png',
x: x * 16,
y: y * 16,
}),
},
{
test: (x, y, noise) => (
!dirtCheck(x, y, noise)
&& !(noise(x / 60, y / 60) < 0.25)
&& noise(x / 5, y / 5) < 0.15
),
compute: (x, y, noise) => ({
anchor:{x: 0.5, y: 0.7},
image: '/assets/ambient/flower.png',
x: x * 16 + (noise(x, y) * 8 - 4),
y: y * 16 + (noise(y, x) * 8 - 4),
}),
},
{
test: (x, y, noise) => (
!dirtCheck(x, y, noise)
&& !(noise(x / 60, y / 60) < 0.25)
&& noise(x / 10, y / 10) < 0.2
),
compute: (x, y, noise) => ({
anchor:{x: 0.5, y: 0.7},
image: '/assets/ambient/shrub.png',
x: x * 16 + (noise(x, y) * 8 - 4),
y: y * 16 + (noise(y, x) * 8 - 4),
}),
},
];
const layer = {
area,
$$chunks: Array(
Math.ceil(area.x / CHUNK_SIZE) * Math.ceil(area.y / CHUNK_SIZE)
).fill(0).map(() => ({})),
data: Array(area.x * area.y).fill(1),
source: '/assets/tileset.json',
tileSize: {x: 16, y: 16},
};
const tileGenerator = new Generator({
area,
passes: tilePasses,
seed,
});
tileGenerator.generate((tile, x, y) => {
layer.data[y * area.x + x] = tile;
});
const entities = [];
const entityGenerator = new Generator({
area,
passes: entityPasses,
seed,
});
entityGenerator.generate((entity) => {
entities.push(entity);
});
return (
<>
<Stage
width={640}
height={640}
options={{
background: 0x0,
}}
>
<AssetsContext.Provider value={assetsTuple}>
<Container
scale={0.5}
>
<TileLayer
tileLayer={layer}
/>
{entities.map((entity, i) => (
<Sprite
key={i}
{...entity}
/>
))}
</Container>
</AssetsContext.Provider>
</Stage>
<input type="text" onChange={({currentTarget: {value}}) => setSeed(value || 0)} value={seed} />
<input
type="range"
min="0"
max="1"
step="0.05"
value={dirtPer}
onChange={({currentTarget: {value}}) => setDirtPer(value)}
/>
<input
type="range"
min="1"
max="100"
step="1"
value={dirtClump}
onChange={({currentTarget: {value}}) => setDirtClump(value)}
/>
</>
);
}
export default Gen;