dev: initial gen ui
This commit is contained in:
parent
9853edec44
commit
cd8a933a5b
186
app/routes/gen/route.jsx
Normal file
186
app/routes/gen/route.jsx
Normal 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;
|
Loading…
Reference in New Issue
Block a user