mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 09:41:24 +01:00
101 lines
3.3 KiB
JavaScript
101 lines
3.3 KiB
JavaScript
"use strict";
|
|
|
|
const pointsGenerators = {
|
|
jittered: generateJitteredPoints,
|
|
hexFlat: generateHexFlatPoints,
|
|
hexPointy: generateHexPointyPoints,
|
|
square: generateSquarePoints
|
|
};
|
|
|
|
function generatePoints() {
|
|
TIME && console.time("placePoints");
|
|
const cellsDesired = +byId("pointsInput").dataset.cells;
|
|
const spacing = Math.sqrt((graphWidth * graphHeight) / cellsDesired); // spacing between points
|
|
const boundary = getBoundaryPoints(graphWidth, graphHeight, spacing);
|
|
|
|
const type = byId("gridType").value;
|
|
const {points, cellsX, cellsY} = pointsGenerators[type](graphWidth, graphHeight, spacing);
|
|
TIME && console.timeEnd("placePoints");
|
|
|
|
return {spacing, cellsDesired, type, boundary, points, cellsX, cellsY};
|
|
}
|
|
|
|
function generateJitteredPoints(width, height, spacing) {
|
|
return generateSquareJitteredPoints(0.9, width, height, spacing);
|
|
}
|
|
|
|
function generateSquarePoints(width, height, spacing) {
|
|
return generateSquareJitteredPoints(0, width, height, spacing);
|
|
}
|
|
|
|
function generateSquareJitteredPoints(jittering, width, height, spacing) {
|
|
const radius = spacing / 2;
|
|
const maxDeviation = radius * jittering;
|
|
const jitter = () => (jittering ? Math.random() * maxDeviation * 2 - maxDeviation : 0);
|
|
|
|
let points = [];
|
|
for (let y = radius; y < height; y += spacing) {
|
|
for (let x = radius; x < width; x += spacing) {
|
|
const xj = Math.min(rn(x + jitter(), 2), width);
|
|
const yj = Math.min(rn(y + jitter(), 2), height);
|
|
points.push([xj, yj]);
|
|
}
|
|
}
|
|
|
|
const cellsX = Math.floor((width + 0.5 * spacing - 1e-10) / spacing);
|
|
const cellsY = Math.floor((height + 0.5 * spacing - 1e-10) / spacing);
|
|
return {points, cellsX, cellsY};
|
|
}
|
|
|
|
function generateHexFlatPoints(width, height, spacing) {
|
|
return generateHexPoints(false, width, height, spacing);
|
|
}
|
|
|
|
function generateHexPointyPoints(width, height, spacing) {
|
|
return generateHexPoints(true, width, height, spacing);
|
|
}
|
|
|
|
function generateHexPoints(isPointy, width, height, spacing) {
|
|
const hexRatio = Math.sqrt(3) / 2;
|
|
const spacingX = isPointy ? spacing / hexRatio : spacing * 2;
|
|
const spacingY = isPointy ? spacing : spacing / hexRatio / 2;
|
|
const maxWidth = width + spacingX / 2;
|
|
const maxHeight = height + spacingY / 2;
|
|
const indentionX = spacingX / 2;
|
|
|
|
let points = [];
|
|
for (let y = 0, row = 0; y < maxHeight; y += spacingY, row++) {
|
|
for (let x = row % 2 ? 0 : indentionX; x < maxWidth; x += spacingX) {
|
|
if (x > width) x = width;
|
|
if (y > height) y = height;
|
|
points.push([rn(x, 2), rn(y, 2)]);
|
|
}
|
|
}
|
|
|
|
const cellsX = Math.ceil(width / spacingX);
|
|
const cellsY = Math.ceil(height / spacingY);
|
|
return {points, cellsX, cellsY};
|
|
}
|
|
|
|
// add points along map edge to pseudo-clip voronoi cells
|
|
function getBoundaryPoints(width, height, spacing) {
|
|
const offset = rn(-1 * spacing);
|
|
const bSpacing = spacing * 2;
|
|
const w = width - offset * 2;
|
|
const h = height - offset * 2;
|
|
const numberX = Math.ceil(w / bSpacing) - 1;
|
|
const numberY = Math.ceil(h / bSpacing) - 1;
|
|
const points = [];
|
|
|
|
for (let i = 0.5; i < numberX; i++) {
|
|
let x = Math.ceil((w * i) / numberX + offset);
|
|
points.push([x, offset], [x, h + offset]);
|
|
}
|
|
|
|
for (let i = 0.5; i < numberY; i++) {
|
|
let y = Math.ceil((h * i) / numberY + offset);
|
|
points.push([offset, y], [w + offset, y]);
|
|
}
|
|
|
|
return points;
|
|
}
|