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