From 436172ee2ff4ea6d0cae8db60eb0fcba4ad3ee6b Mon Sep 17 00:00:00 2001 From: Azgaar Date: Sun, 9 Jun 2019 22:00:55 +0300 Subject: [PATCH] v 0.9b --- index.css | 31 +-- index.html | 412 +++++++++++++++++++++++++++++------- main.js | 28 +-- modules/relief-icons.js | 34 ++- modules/save-and-load.js | 11 +- modules/ui/relief-editor.js | 33 ++- 6 files changed, 420 insertions(+), 129 deletions(-) diff --git a/index.css b/index.css index 7ba47551..4c8668cc 100644 --- a/index.css +++ b/index.css @@ -1502,33 +1502,38 @@ svg.button { width: 15em; } +#reliefEditor input[type="number"] { + width: 3em; +} + #reliefIconsDiv { margin-top: 2px; - border: 1px solid #d4d4d4; - padding: 2px; + padding: 2px; + max-width: 30vw; } -#reliefIconsDiv > button { +#reliefIconsDiv > svg { + width: 40px; + height: 40px; border-radius: 15%; - border: 1px solid #939393; - background-color: #eef6fb; + border: 1px solid #a9a9a9; + cursor: pointer; } -#reliefIconsDiv > button:hover { +#reliefIconsDiv > svg:hover { border-color: #5c5c5c; + background-color: #eef6fb; } -#reliefIconsDiv > button.pressed { - border: 1.5px outset #a6a6da; - background-color: #ecd8d8; +#reliefIconsDiv > svg.pressed { + border: 1px solid #b3352c; + background-color: #eef6fb; } #reliefIconsSeletionAny { display: none; - font-style: italic; - width: 24px; - height: 18px; - padding: 0; + text-anchor: middle; + dominant-baseline: central; } #alertMessage { diff --git a/index.html b/index.html index 87f3ce9a..5e44f971 100644 --- a/index.html +++ b/index.html @@ -16,8 +16,8 @@ - - + + @@ -153,6 +153,294 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -254,7 +542,7 @@
Azgaar's
Fantasy Map Generator
-
v. 0.8b
+
v. 0.9b

LOADING...

@@ -551,7 +839,7 @@ Density - + 40% @@ -1309,87 +1597,67 @@
Size:
- - + +
- + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - + Any
@@ -2041,7 +2309,7 @@ - + diff --git a/main.js b/main.js index 3c1b4243..2cc47efc 100644 --- a/main.js +++ b/main.js @@ -7,7 +7,7 @@ // See also https://github.com/Azgaar/Fantasy-Map-Generator/issues/153 "use strict"; -const version = "0.80b"; // generator version +const version = "0.9b"; // generator version document.title += " v " + version; // append svg layers (in default order) @@ -112,29 +112,22 @@ setTimeout(showWelcomeMessage, 8000); function showWelcomeMessage() { // Changelog dialog window if (localStorage.getItem("version") != version) { - const link = 'https://www.reddit.com/r/FantasyMapGenerator/comments/bfskpi/update_stable_version_is_released_v_08b/?utm_source=share&utm_medium=web2x'; // announcement on Reddit + const link = 'https://www.reddit.com/r/FantasyMapGenerator/comments/bynoz7/update_new_version_is_published_v_09b/'; // announcement on Reddit alertMessage.innerHTML = `The Fantasy Map Generator is updated up to version ${version}. - This version is not compatible with older .map files. - Please use an archived version to open the file. + This version is compatible with v 0.8b, but not with older .map files. + Please use an archived version to open old files.
    Main changes: -
  • World size and climate configuration
  • -
  • Biomes layer and biomes editor
  • -
  • Temperature and precipitation layers
  • -
  • Reworked population model (now depends on biome)
  • -
  • New states and cultures spread algorithm
  • -
  • 15 new cultures
  • -
  • Texture layer and ability to link a custom texture
  • -
  • Seed history (to open previously generated maps)
  • -
  • Optimization (faster generation and smoother edit experience)
  • -
  • UI and usability changes
  • -
  • Reworked hotkeys
  • +
  • Relief icons by Arzak Rubin
  • +
  • Ability to re-generate Burgs
  • +
  • Ability to re-generate States
  • +
  • Bug fixes

Join our Reddit community and Discord server - to share created maps, discuss the Generator, report bugs, ask questions and propose new features.

+ to ask questions, share maps, discuss the Generator, report bugs and propose new features.

Thanks for all supporters on Patreon!

`; @@ -233,7 +226,8 @@ function applyDefaultBiomesSystem() { const i = new Uint8Array(d3.range(0, name.length)); const habitability = new Uint16Array([0,2,5,15,25,50,100,80,90,10,2,0]); const iconsDensity = new Uint8Array([0,3,2,120,120,120,120,150,150,100,5,0]); - const icons = [{},{dune:1},{dune:1},{acacia:1, grass:9},{grass:1},{acacia:1, palm:1},{deciduous:1},{acacia:7, palm:2, deciduous:1},{deciduous:7, swamp:3},{conifer:1},{grass:1},{}]; + //const icons = [{},{dune:1},{dune:1},{acacia:1, grass:9},{grass:1},{acacia:1, palm:1},{deciduous:1},{acacia:7, palm:2, deciduous:1},{deciduous:7, swamp:3},{conifer:1},{grass:1},{}]; + const icons = [{},{dune:3, cactus:6, deadTree:1},{dune:9, deadTree:1},{acacia:1, grass:9},{grass:1},{acacia:8, palm:1},{deciduous:1},{acacia:5, palm:3, deciduous:1, swamp:2},{deciduous:5, swamp:3},{conifer:1},{grass:1},{}]; const cost = new Uint8Array([10,200,150,60,50,70,70,80,90,80,100,255]); // biome movement cost const biomesMartix = [ new Uint8Array([1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2]), diff --git a/modules/relief-icons.js b/modules/relief-icons.js index 12f45216..72e4dd1d 100644 --- a/modules/relief-icons.js +++ b/modules/relief-icons.js @@ -34,15 +34,15 @@ for (const [cx, cy] of poissonDiscSampler(e[0], e[1], e[2], e[3], radius)) { if (!d3.polygonContains(polygon, [cx, cy])) continue; let h = rn((4 + Math.random()) * size, 2); - const icon = getBiomeIcon(biomesData.icons[b]); + const icon = getBiomeIcon(i, biomesData.icons[b]); if (icon === "#relief-grass-1") h *= 1.3; relief.push({t: icon, c: i, x: rn(cx-h, 2), y: rn(cy-h, 2), s: h*2}); } } - function placeReliefIcons() { + function placeReliefIcons(i) { const radius = 2 / density; - const [icon, h] = getReliefIcon(height); + const [icon, h] = getReliefIcon(i, height); for (const [cx, cy] of poissonDiscSampler(e[0], e[1], e[2], e[3], radius)) { if (!d3.polygonContains(polygon, [cx, cy])) continue; @@ -50,10 +50,11 @@ } } - function getReliefIcon(h) { - const type = h > 70 ? "mount" : "hill"; + function getReliefIcon(i, h) { + const temp = grid.cells.temp[pack.cells.g[i]]; + const type = h > 70 && temp < 0 ? "mountSnow" : h > 70 ? "mount" : "hill"; const size = h > 70 ? (h - 45) * mod : Math.min(Math.max((h - 40) * mod, 3), 6); - return ["#relief-" + type + "-1", size]; + return ["#relief-" + type + "-" + getIcon(type), size]; } } @@ -71,8 +72,25 @@ console.timeEnd('drawRelief'); } - function getBiomeIcon(i) { - return "#relief-" + i[Math.floor(Math.random() * i.length)] + "-1"; + function getBiomeIcon(i, b) { + let type = b[Math.floor(Math.random() * b.length)]; + const temp = grid.cells.temp[pack.cells.g[i]]; + if (type === "conifer" && temp < 0) type = "coniferSnow"; + return "#relief-" + type + "-" + getIcon(type); + } + + function getIcon(type) { + switch (type) { + case "mount": return rand(2,7); + case "mountSnow": return rand(1,6); + case "hill": return rand(2,5); + case "conifer": return 2; + case "coniferSnow": return 1; + case "swamp": return rand(2,3); + case "cactus": return rand(1,3); + case "deadTree": return rand(1,2); + default: return 2; + } } return ReliefIcons; diff --git a/modules/save-and-load.js b/modules/save-and-load.js index bc5538ae..f82cd044 100644 --- a/modules/save-and-load.js +++ b/modules/save-and-load.js @@ -217,6 +217,7 @@ function uploadFile(file, callback) { function parseLoadedData(data) { closeDialogs(); + const reliefIcons = document.getElementById("defs-relief").innerHTML; // save relief icons void function parseParameters() { const params = data[0].split("|"); @@ -385,8 +386,14 @@ function parseLoadedData(data) { }() void function resolveVersionConflicts() { - document.getElementById("regions").removeAttribute("opacity"); // 0.8.28b changed opacity slider from regions to statesBody - } + if (parseFloat(data[0].split("|")[0]) == 0.8) { + // 0.9 has additional relief icons to be included into older maps + document.getElementById("defs-relief").innerHTML = reliefIcons; + + // 0.8.28b changed opacity slider from regions to statesBody + document.getElementById("regions").removeAttribute("opacity"); + } + }() changeMapSize(); restoreDefaultEvents(); diff --git a/modules/ui/relief-editor.js b/modules/ui/relief-editor.js index 5a01dab7..52d7c7f5 100644 --- a/modules/ui/relief-editor.js +++ b/modules/ui/relief-editor.js @@ -5,7 +5,7 @@ function editReliefIcon() { if (!layerIsOn("toggleRelief")) toggleRelief(); terrain.selectAll("use").call(d3.drag().on("drag", dragReliefIcon)).classed("draggable", true); - elSelected = d3.select(d3.event.target); + elSelected = d3.select(d3.event.target); restoreEditMode(); updateReliefIconSelected(); @@ -27,7 +27,7 @@ function editReliefIcon() { document.getElementById("reliefSize").addEventListener("input", changeIconSize); document.getElementById("reliefSizeNumber").addEventListener("input", changeIconSize); - reliefIconsDiv.querySelectorAll("button").forEach(el => el.addEventListener("click", changeIcon)); + reliefIconsDiv.querySelectorAll("svg").forEach(el => el.addEventListener("click", changeIcon)); document.getElementById("reliefCopy").addEventListener("click", copyIcon); document.getElementById("reliefMoveFront").addEventListener("click", () => elSelected.raise()); @@ -53,8 +53,8 @@ function editReliefIcon() { function updateReliefIconSelected() { const type = elSelected.attr("data-type"); - reliefIconsDiv.querySelectorAll("button.pressed").forEach(b => b.classList.remove("pressed")); - reliefIconsDiv.querySelector("button[data-type='"+type+"']").classList.add("pressed"); + reliefIconsDiv.querySelectorAll("svg.pressed").forEach(b => b.classList.remove("pressed")); + reliefIconsDiv.querySelector("svg[data-type='"+type+"']").classList.add("pressed"); } function updateReliefSizeInput() { @@ -85,10 +85,10 @@ function editReliefIcon() { reliefSpacingDiv.style.display = "block"; reliefIconsSeletionAny.style.display = "none"; - const pressedType = reliefIconsDiv.querySelector("button.pressed"); + const pressedType = reliefIconsDiv.querySelector("svg.pressed"); if (pressedType.id === "reliefIconsSeletionAny") { // in "any" is pressed, select first type - reliefIconsSeletionAny.classList.remove("pressed"); - reliefIconsDiv.querySelector("button").classList.add("pressed"); + reliefIconsSeletionAny.classList.remove("pressed"); + reliefIconsDiv.querySelector("svg").classList.add("pressed"); } viewbox.style("cursor", "crosshair").call(d3.drag().on("start", dragToAdd)).on("touchmove mousemove", moveBrush); @@ -98,18 +98,18 @@ function editReliefIcon() { function moveBrush() { showMainTip(); const point = d3.mouse(this); - const radius = +reliefRadius.value; + const radius = +reliefRadiusNumber.value; moveCircle(point[0], point[1], radius); } function dragToAdd() { - const pressed = reliefIconsDiv.querySelector("button.pressed"); + const pressed = reliefIconsDiv.querySelector("svg.pressed"); if (!pressed) {tip("Please select an icon", false, error); return;} const type = pressed.dataset.type; - const r = +reliefRadius.value; - const spacing = +reliefSpacing.value; - const size = +reliefSize.value; + const r = +reliefRadiusNumber.value; + const spacing = +reliefSpacingNumber.value; + const size = +reliefSizeNumber.value; // build a quadtree const tree = d3.quadtree(); @@ -166,10 +166,10 @@ function editReliefIcon() { } function dragToRemove() { - const pressed = reliefIconsDiv.querySelector("button.pressed"); + const pressed = reliefIconsDiv.querySelector("svg.pressed"); if (!pressed) {tip("Please select an icon", false, error); return;} - const r = +reliefRadius.value; + const r = +reliefRadiusNumber.value; const type = pressed.dataset.type; const icons = type ? terrain.selectAll("use[data-type='"+type+"']") : terrain.selectAll("use"); const tree = d3.quadtree(); @@ -187,8 +187,7 @@ function editReliefIcon() { } function changeIconSize() { - const size = +reliefSize.value; - reliefSize.value = reliefSizeNumber.value = size; + const size = +reliefSizeNumber.value; if (!reliefIndividual.classList.contains("pressed")) return; const shift = (size - +elSelected.attr("width")) / 2; @@ -200,7 +199,7 @@ function editReliefIcon() { function changeIcon() { if (this.classList.contains("pressed")) return; - reliefIconsDiv.querySelectorAll("button.pressed").forEach(b => b.classList.remove("pressed")) + reliefIconsDiv.querySelectorAll("svg.pressed").forEach(b => b.classList.remove("pressed")) this.classList.add("pressed"); if (reliefIndividual.classList.contains("pressed")) {