From f81fd8a94c2b3a7aaf8426c0597df5f7f290b7a3 Mon Sep 17 00:00:00 2001 From: Azgaar Date: Sat, 4 May 2019 20:12:47 +0300 Subject: [PATCH] v 0.8.14b --- index.css | 5 +++ index.html | 20 ++++++------ main.js | 4 +-- modules/burgs-and-states.js | 8 ++--- modules/heightmap-generator.js | 57 +++++++++++++++++++++++++++------- modules/ui/general.js | 3 +- modules/ui/options.js | 26 +++++++++------- modules/utils.js | 18 ++++++++++- 8 files changed, 100 insertions(+), 41 deletions(-) diff --git a/index.css b/index.css index e715cdb6..5682afa5 100644 --- a/index.css +++ b/index.css @@ -378,6 +378,11 @@ input[type="color"]::-webkit-color-swatch-wrapper { font-size: smaller; } +#optionsContent output { + text-align: right; + font-size: smaller; +} + #optionsContent input[type="number"] { border: 0; text-align: right; diff --git a/index.html b/index.html index dbb9f9e1..4c94d18a 100644 --- a/index.html +++ b/index.html @@ -807,14 +807,14 @@ - + - Cells density + Points number - + - + 10K @@ -852,7 +852,7 @@ - + @@ -865,7 +865,7 @@ - + @@ -891,16 +891,16 @@ - + - Burgs density + Towns number - + - + diff --git a/main.js b/main.js index 118bc620..9940a275 100644 --- a/main.js +++ b/main.js @@ -1153,7 +1153,7 @@ function showStatistics() { console.log(stats); } -function regenerateMap() { +const regenerateMap = debounce(function() { closeDialogs("#worldConfigurator"); customization = 0; undraw(); @@ -1161,7 +1161,7 @@ function regenerateMap() { generate(); restoreLayers(); if ($("#worldConfigurator").is(":visible")) editWorld(); -} +}, 500); // Clear the map function undraw() { diff --git a/modules/burgs-and-states.js b/modules/burgs-and-states.js index ec807a70..6ffdb21c 100644 --- a/modules/burgs-and-states.js +++ b/modules/burgs-and-states.js @@ -106,12 +106,12 @@ const score = new Int16Array(cells.s.map(s => s * Math.random())); // cell score for towns placement const sorted = cells.i.filter(i => score[i] > 0 && cells.culture[i]).sort((a, b) => score[b] - score[a]); // filtered and sorted array of indexes - // burgs number depends on ratio between populated and all cells and burgsDensity input (expected mean ~300)) - const burgsCount = rn(sorted.length / grid.points.length * manorsInput.value * 1000); + let burgsCount = manorsInput.value == 1000 ? rn(sorted.length / 10 / densityInput.value ** .8) : +manorsInput.value; + burgsCount += burgs.length; const spacing = (graphWidth + graphHeight) * 9 / burgsCount; // base min distance between towns const burgsTree = burgs[0]; - for (let i = 0; burgs.length <= burgsCount && i < sorted.length; i++) { + for (let i = 0; burgs.length < burgsCount && i < sorted.length; i++) { const id = sorted[i], x = cells.p[id][0], y = cells.p[id][1]; const s = spacing * Math.random() + 0.5; // randomize to make the placement not uniform if (burgsTree.find(x, y, s) !== undefined) continue; // to close to existing burg @@ -124,7 +124,7 @@ cells.burg[id] = burg; } - if (burgs.length <= burgsCount) console.error(`Cannot place all burgs. Requested ${burgsCount}, placed ${burgs.length-1}`); + if (burgs.length < burgsCount) console.error(`Cannot place all burgs. Requested ${burgsCount}, placed ${burgs.length-1}`); //const min = d3.min(score.filter(s => s)), max = d3.max(score); //terrs.selectAll("polygon").data(sorted).enter().append("polygon").attr("points", d => getPackPolygon(d)).attr("fill", d => color(1 - normalize(score[d], min, max))); diff --git a/modules/heightmap-generator.js b/modules/heightmap-generator.js index ff707a3c..4cb8c00c 100644 --- a/modules/heightmap-generator.js +++ b/modules/heightmap-generator.js @@ -174,9 +174,40 @@ addStep("Trough", "3-4", "25-35", "5-95", "80-90"); addStep("Range", "5-6", "30-40", "10-90", "35-65"); } + + function getBlobPower() { + switch (+densityInput.value) { + case 1: return .98; + case 2: return .985; + case 3: return .987; + case 4: return .9892; + case 5: return .9911; + case 6: return .9921; + case 7: return .9934; + case 8: return .9942; + case 9: return .9946; + case 10: return .995; + } + } + + function getLinePower() { + switch (+densityInput.value) { + case 1: return .81; + case 2: return .82; + case 3: return .83; + case 4: return .84; + case 5: return .855; + case 6: return .87; + case 7: return .885; + case 8: return .91; + case 9: return .92; + case 10: return .93; + } + } const addHill = function(count, height, rangeX, rangeY) { count = getNumberInRange(count); + const power = getBlobPower(); while (count >= 1 || Math.random() < count) {addOneHill(); count--;} function addOneHill() { @@ -198,7 +229,7 @@ for (const c of cells.c[q]) { if (change[c]) continue; - change[c] = change[q] ** .98 * (Math.random() * .2 + .9); + change[c] = change[q] ** power * (Math.random() * .2 + .9); if (change[c] > 1) queue.push(c); } } @@ -227,7 +258,7 @@ const queue = [start]; while (queue.length) { const q = queue.shift(); - h = h ** .98 * (Math.random() * .2 + .9); + h = h ** getBlobPower() * (Math.random() * .2 + .9); if (h < 1) return; cells.c[q].forEach(function(c, i) { @@ -242,13 +273,14 @@ const addRange = function(count, height, rangeX, rangeY) { count = getNumberInRange(count); - while (count >= 1 || Math.random() < count) {addOneRange(); count--;} + const power = getLinePower(); + while (count >= 1 || Math.random() < count) {addOneRange(); count--;} function addOneRange() { const used = new Uint8Array(cells.h.length); let h = lim(getNumberInRange(height)); - // find start and end points + // find start and end points const startX = getPointInRange(rangeX, graphWidth); const startY = getPointInRange(rangeY, graphHeight); @@ -260,7 +292,7 @@ limit++; } while ((dist < graphWidth / 8 || dist > graphWidth / 3) && limit < 50) - let range = getRange(findGridCell(startX, startY), findGridCell(endX, endY)); + let range = getRange(findGridCell(startX, startY), findGridCell(endX, endY)); // get main ridge function getRange(cur, end) { @@ -291,11 +323,11 @@ frontier.forEach(i => { cells.h[i] = lim(cells.h[i] + h * (Math.random() * .3 + .85)); }); - h = h ** .82 - 1; + h = h ** power - 1; if (h < 2) break; frontier.forEach(f => { cells.c[f].forEach(i => { - if (!used[i]) {queue.push(i); used[i] = 1;} + if (!used[i]) {queue.push(i); used[i] = 1;} }); }); } @@ -316,13 +348,14 @@ const addTrough = function(count, height, rangeX, rangeY) { count = getNumberInRange(count); - while (count >= 1 || Math.random() < count) {addOneTrough(); count--;} + const power = getLinePower(); + while (count >= 1 || Math.random() < count) {addOneTrough(); count--;} function addOneTrough() { const used = new Uint8Array(cells.h.length); let h = lim(getNumberInRange(height)); - // find start and end points + // find start and end points let limit = 0, startX, startY, start, dist = 0, endX, endY; do { startX = getPointInRange(rangeX, graphWidth); @@ -370,11 +403,11 @@ frontier.forEach(i => { cells.h[i] = lim(cells.h[i] - h * (Math.random() * .3 + .85)); }); - h = h ** .8 - 1; + h = h ** power - 1; if (h < 2) break; frontier.forEach(f => { cells.c[f].forEach(i => { - if (!used[i]) {queue.push(i); used[i] = 1;} + if (!used[i]) {queue.push(i); used[i] = 1;} }); }); } @@ -405,7 +438,7 @@ const start = findGridCell(startX, startY), end = findGridCell(endX, endY); let range = getRange(start, end); - const query = []; + const query = []; function getRange(cur, end) { const range = []; diff --git a/modules/ui/general.js b/modules/ui/general.js index 6597ac15..6b8359a6 100644 --- a/modules/ui/general.js +++ b/modules/ui/general.js @@ -77,10 +77,11 @@ function showMapTooltip(e, i, g) { tip(""); // clear tip const tag = e.target.tagName; const path = e.composedPath ? e.composedPath() : getComposedPath(e.target); // apply polyfill + if (!path[path.length - 8]) return; const group = path[path.length - 7].id; const subgroup = path[path.length - 8].id; const land = pack.cells.h[i] >= 20; - + // specific elements if (group === "rivers") {tip("Click to edit the River"); return;} if (group === "routes") {tip("Click to edit the Route"); return;} diff --git a/modules/ui/options.js b/modules/ui/options.js index f3e3cafd..f9938730 100644 --- a/modules/ui/options.js +++ b/modules/ui/options.js @@ -590,7 +590,7 @@ const optionsContent = document.getElementById("optionsContent"); optionsContent.addEventListener("input", function(event) { const id = event.target.id, value = event.target.value; if (id === "mapWidthInput" || id === "mapHeightInput") mapSizeInputChange(); - else if (id === "densityInput" || id === "densityOutput") changeCellsDensity(value); + else if (id === "densityInput" || id === "densityOutput") changeCellsDensity(+value); else if (id === "culturesInput") culturesOutput.value = value; else if (id === "culturesOutput") culturesInput.value = value; else if (id === "regionsInput" || id === "regionsOutput") changeStatesNumber(value); @@ -598,8 +598,7 @@ optionsContent.addEventListener("input", function(event) { else if (id === "powerOutput") powerInput.value = value; else if (id === "neutralInput") neutralOutput.value = value; else if (id === "neutralOutput") neutralInput.value = value; - else if (id === "manorsInput") manorsOutput.value = value; - else if (id === "manorsOutput") manorsInput.value = value; + else if (id === "manorsInput") changeBurgsNumberSlider(value); else if (id === "uiSizeInput" || id === "uiSizeOutput") changeUIsize(value); else if (id === "tooltipSizeInput" || id === "tooltipSizeOutput") changeTooltipSize(value); else if (id === "transparencyInput") changeDialogsTransparency(value); @@ -608,9 +607,10 @@ optionsContent.addEventListener("input", function(event) { }); optionsContent.addEventListener("change", function(event) { - if (event.target.dataset.stored) lock(event.target.dataset.stored); + if (event.target.dataset.stored) lock(event.target.dataset.stored); const id = event.target.id, value = event.target.value; if (id === "zoomExtentMin" || id === "zoomExtentMax") changeZoomExtent(value); + else if (id === "optionsSeed") generateMapWithSeed(); }); optionsContent.addEventListener("click", function(event) { @@ -625,7 +625,7 @@ function mapSizeInputChange() { changeMapSize(); autoResize = false; localStorage.setItem("mapWidth", mapWidthInput.value); - localStorage.setItem("mapHeight", mapHeightInput.value); + localStorage.setItem("mapHeight", mapHeightInput.value); } // change svg size on manual size change or window resize, do not change graph size @@ -658,7 +658,7 @@ function toggleFullscreen() { mapWidthInput.value = graphWidth; mapHeightInput.value = graphHeight; } - changeMapSize(); + changeMapSize(); } function generateMapWithSeed() { @@ -703,10 +703,10 @@ function restoreDefaultZoomExtent() { } function changeCellsDensity(value) { - densityInput.value = densityOutput.value = value; - if (value == 3) densityOutput.style.color = "red"; - else if (value == 2) densityOutput.style.color = "yellow"; - else if (value == 1) densityOutput.style.color = "green"; + densityOutput.value = value * 10 + "K"; + if (value > 5) densityOutput.style.color = "#b12117"; + else if (value > 1) densityOutput.style.color = "#dfdf12"; + else densityOutput.style.color = "#038603"; } function changeStatesNumber(value) { @@ -715,6 +715,10 @@ function changeStatesNumber(value) { labels.select("#countries").attr("data-size", Math.max(rn(18 - value / 6), 4)); } +function changeBurgsNumberSlider(value) { + manorsOutput.value = value == 1000 ? "auto" : value; +} + function changeUIsize(value) { uiSizeInput.value = uiSizeOutput.value = value; document.getElementsByTagName("body")[0].style.fontSize = value * 11 + "px"; @@ -785,7 +789,7 @@ function applyStoredOptions() { function randomizeOptions() { Math.seedrandom(seed); // reset seed to initial one if (!locked("regions")) regionsInput.value = regionsOutput.value = rand(12, 17); - if (!locked("manors")) manorsInput.value = manorsOutput.value = rn(0.5 + Math.random(), 1); + if (!locked("manors")) {manorsInput.value = 1000; manorsOutput.value = "auto";} if (!locked("power")) powerInput.value = powerOutput.value = rand(0, 4); if (!locked("neutral")) neutralInput.value = neutralOutput.value = rn(0.8 + Math.random(), 1); if (!locked("cultures")) culturesInput.value = culturesOutput.value = rand(10, 15); diff --git a/modules/utils.js b/modules/utils.js index 3cc74eaa..a9959759 100644 --- a/modules/utils.js +++ b/modules/utils.js @@ -433,4 +433,20 @@ function getAbsolutePath(href) { var link = document.createElement("a"); link.href = href; return link.href; -} \ No newline at end of file +} + +// from https://davidwalsh.name/javascript-debounce-function +function debounce(func, wait, immediate) { + var timeout; + return function() { + var context = this, args = arguments; + var later = function() { + timeout = null; + if (!immediate) func.apply(context, args); + } + var callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if (callNow) func.apply(context, args); + } +}; \ No newline at end of file