This commit is contained in:
Azgaar 2019-09-12 23:24:32 +03:00
parent cbc702bfde
commit a3256e6726
17 changed files with 187 additions and 116 deletions

View file

@ -394,7 +394,7 @@ input[type="color"]::-webkit-color-swatch-wrapper {
#options input[type="number"] { #options input[type="number"] {
height: 1.3em; height: 1.3em;
line-height: 14px; line-height: 1.2em;
font-size: .8em; font-size: .8em;
} }
@ -440,7 +440,10 @@ input[type="color"]::-webkit-color-swatch-wrapper {
#optionsContent input.long { #optionsContent input.long {
width: 100%; width: 100%;
background-color: white; background-color: white;
text-align: center; text-align: left;
padding-left: 0.4em;
box-sizing: border-box;
height: 1.5em;
} }
#optionsContent input[type="range"] { #optionsContent input[type="range"] {

View file

@ -10,7 +10,7 @@
<meta name="google" content="notranslate"> <meta name="google" content="notranslate">
<meta property="og:url" content="https://azgaar.github.io/Fantasy-Map-Generator"> <meta property="og:url" content="https://azgaar.github.io/Fantasy-Map-Generator">
<meta property="og:title" content="Azgaar's Fantasy Map Generator"> <meta property="og:title" content="Azgaar's Fantasy Map Generator">
<meta property="og:description" content="Based on Voronoi diagram rendered to svg"> <meta property="og:description" content="Web application generating interactive and customizable maps">
<meta property="og:image" content="images/preview.png"> <meta property="og:image" content="images/preview.png">
<link rel="icon" type="image/png" href="images/favicon-32x32.png" sizes="32x32"/> <link rel="icon" type="image/png" href="images/favicon-32x32.png" sizes="32x32"/>
<link rel="icon" type="image/png" href="images/favicon-16x16.png" sizes="16x16"/> <link rel="icon" type="image/png" href="images/favicon-16x16.png" sizes="16x16"/>
@ -1511,6 +1511,19 @@
</td> </td>
</tr> </tr>
<tr data-tip="Click to set up map name to be used for downloaded files">
<td>
<i data-locked=0 id="lock_mapName" class="icon-lock-open"></i>
</td>
<td>Map name</td>
<td>
<input id="mapName" data-stored="mapName" class="long" autocorrect="off" spellcheck="false" type="text">
</td>
<td>
<i data-tip="Regenerate map name" onclick="Names.getMapName()" class="icon-arrows-cw"></i>
</td>
</tr>
<tr data-tip="Select template to be used for a Heightmap generation"> <tr data-tip="Select template to be used for a Heightmap generation">
<td> <td>
<i data-locked=0 id="lock_template" class="icon-lock-open"></i> <i data-locked=0 id="lock_template" class="icon-lock-open"></i>
@ -2962,6 +2975,7 @@
<script src="libs/polylabel.min.js"></script> <script src="libs/polylabel.min.js"></script>
<script src="libs/jquery-ui.min.js"></script> <script src="libs/jquery-ui.min.js"></script>
<script src="libs/seedrandom.min.js"></script> <script src="libs/seedrandom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/simplex-noise/2.3.0/simplex-noise.js"></script>
<script src="modules/ui/layers.js"></script> <script src="modules/ui/layers.js"></script>
<script defer src="modules/ui/general.js"></script> <script defer src="modules/ui/general.js"></script>

View file

@ -605,6 +605,7 @@ function generate() {
BurgsAndStates.drawStateLabels(); BurgsAndStates.drawStateLabels();
addZone(); addZone();
addMarkers(); addMarkers();
Names.getMapName();
console.warn(`TOTAL: ${rn((performance.now()-timeStart)/1000,2)}s`); console.warn(`TOTAL: ${rn((performance.now()-timeStart)/1000,2)}s`);
showStatistics(); showStatistics();

View file

@ -156,7 +156,10 @@
else if (base === 17) suffix = rnd < .8 ? "a" : "ia"; // Berber else if (base === 17) suffix = rnd < .8 ? "a" : "ia"; // Berber
else if (base === 18) suffix = rnd < .8 ? "a" : "ia"; // Arabic else if (base === 18) suffix = rnd < .8 ? "a" : "ia"; // Arabic
else suffix = "ia" // other else suffix = "ia" // other
return validateSuffix(name, suffix);
}
function validateSuffix(name, suffix) {
if (name.slice(-1 * suffix.length) === suffix) return name; // no suffix if name already ends with it if (name.slice(-1 * suffix.length) === suffix) return name; // no suffix if name already ends with it
const s1 = suffix.charAt(0); const s1 = suffix.charAt(0);
if (name.slice(-1) === s1) name = name.slice(0, -1); // remove name last letter if it's a suffix first letter if (name.slice(-1) === s1) name = name.slice(0, -1); // remove name last letter if it's a suffix first letter
@ -165,6 +168,24 @@
return name + suffix; return name + suffix;
} }
// generato name for the map
const getMapName = function() {
if (locked("mapName")) return;
const base = Math.random() < .7 ? 2 : Math.random() < .5 ? rand(0, 6) : rand(0, 31);
if (!nameBases[base]) {tip("Namebase is not found", false, "error"); return ""};
const min = nameBases[base].min-1;
const max = Math.max(nameBases[base].max-3, min);
const baseName = getBase(base, min, max, "", 0);
const name = Math.random() < .7 ? addSuffix(baseName) : baseName;
mapName.value = name;
}
function addSuffix(name) {
const suffix = Math.random() < .8 ? "ia" : "land";
if (suffix === "ia" && name.length > 6) name = name.slice(0, -(name.length-3)); else
if (suffix === "land" && name.length > 6) name = name.slice(0, -(name.length-5));
return validateSuffix(name, suffix);
}
const getNameBases = function() { const getNameBases = function() {
// name, min length, max length, letters to allow duplication, multi-word name rate // name, min length, max length, letters to allow duplication, multi-word name rate
@ -241,5 +262,5 @@ const getNameBase = function() {
]; ];
} }
return {getBase, getCulture, getCultureShort, getState, updateChain, updateChains, getNameBase, getNameBases}; return {getBase, getCulture, getCultureShort, getState, updateChain, updateChains, getNameBase, getNameBases, getMapName};
}))); })));

View file

@ -69,7 +69,7 @@ function saveAsImage(type) {
img.onload = function() { img.onload = function() {
window.URL.revokeObjectURL(url); window.URL.revokeObjectURL(url);
ctx.drawImage(img, 0, 0, canvas.width, canvas.height); ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
link.download = "fantasy_map_" + Date.now() + ".png"; link.download = getFileName() + ".png";
canvas.toBlob(function(blob) { canvas.toBlob(function(blob) {
link.href = window.URL.createObjectURL(blob); link.href = window.URL.createObjectURL(blob);
document.body.appendChild(link); document.body.appendChild(link);
@ -81,7 +81,7 @@ function saveAsImage(type) {
}); });
} }
} else { } else {
link.download = "fantasy_map_" + Date.now() + ".svg"; link.download = getFileName() + ".svg";
link.href = url; link.href = url;
document.body.appendChild(link); document.body.appendChild(link);
link.click(); link.click();
@ -161,9 +161,13 @@ function getMapData() {
const dateString = date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate(); const dateString = date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate();
const license = "File can be loaded in azgaar.github.io/Fantasy-Map-Generator"; const license = "File can be loaded in azgaar.github.io/Fantasy-Map-Generator";
const params = [version, license, dateString, seed, graphWidth, graphHeight].join("|"); const params = [version, license, dateString, seed, graphWidth, graphHeight].join("|");
const options = [distanceUnitInput.value, distanceScaleInput.value, areaUnit.value, heightUnit.value, heightExponentInput.value, temperatureScale.value, const options = [distanceUnitInput.value, distanceScaleInput.value, areaUnit.value,
barSize.value, barLabel.value, barBackOpacity.value, barBackColor.value, barPosX.value, barPosY.value, populationRate.value, urbanization.value, heightUnit.value, heightExponentInput.value, temperatureScale.value,
mapSizeOutput.value, latitudeOutput.value, temperatureEquatorOutput.value, temperaturePoleOutput.value, precOutput.value, JSON.stringify(winds)].join("|"); barSize.value, barLabel.value, barBackOpacity.value, barBackColor.value,
barPosX.value, barPosY.value, populationRate.value, urbanization.value,
mapSizeOutput.value, latitudeOutput.value, temperatureEquatorOutput.value,
temperaturePoleOutput.value, precOutput.value, JSON.stringify(winds),
mapName.value].join("|");
const coords = JSON.stringify(mapCoordinates); const coords = JSON.stringify(mapCoordinates);
const biomes = [biomesData.color, biomesData.habitability, biomesData.name].join("|"); const biomes = [biomesData.color, biomesData.habitability, biomesData.name].join("|");
const notesData = JSON.stringify(notes); const notesData = JSON.stringify(notes);
@ -217,7 +221,7 @@ async function saveMap() {
const blob = await getMapData(); const blob = await getMapData();
const URL = window.URL.createObjectURL(blob); const URL = window.URL.createObjectURL(blob);
const link = document.createElement("a"); const link = document.createElement("a");
link.download = "fantasy_map_" + Date.now() + ".map"; link.download = getFileName() + ".map";
link.href = URL; link.href = URL;
document.body.appendChild(link); document.body.appendChild(link);
link.click(); link.click();
@ -260,7 +264,7 @@ function saveGeoJSON_Roads() {
const url = window.URL.createObjectURL(dataBlob); const url = window.URL.createObjectURL(dataBlob);
const link = document.createElement("a"); const link = document.createElement("a");
document.body.appendChild(link); document.body.appendChild(link);
link.download = "fmg_routes_" + Date.now() + ".geojson"; link.download = getFileName("Routes") + ".geojson";
link.href = url; link.href = url;
link.click(); link.click();
window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000); window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000);
@ -285,7 +289,7 @@ function saveGeoJSON_Rivers() {
const url = window.URL.createObjectURL(dataBlob); const url = window.URL.createObjectURL(dataBlob);
const link = document.createElement("a"); const link = document.createElement("a");
document.body.appendChild(link); document.body.appendChild(link);
link.download = "fmg_rivers_" + Date.now() + ".geojson"; link.download = getFileName("Rivers") + ".geojson";
link.href = url; link.href = url;
link.click(); link.click();
window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000); window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000);
@ -359,7 +363,7 @@ function saveGeoJSON_Cells() {
const url = window.URL.createObjectURL(dataBlob); const url = window.URL.createObjectURL(dataBlob);
const link = document.createElement("a"); const link = document.createElement("a");
document.body.appendChild(link); document.body.appendChild(link);
link.download = "fmg_cells_" + Date.now() + ".geojson"; link.download = getFileName("Cells") + ".geojson";
link.href = url; link.href = url;
link.click(); link.click();
window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000); window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000);
@ -436,6 +440,7 @@ function parseLoadedData(data) {
if (options[17]) temperaturePoleInput.value = temperaturePoleOutput.value = options[17]; if (options[17]) temperaturePoleInput.value = temperaturePoleOutput.value = options[17];
if (options[18]) precInput.value = precOutput.value = options[18]; if (options[18]) precInput.value = precOutput.value = options[18];
if (options[19]) winds = JSON.parse(options[19]); if (options[19]) winds = JSON.parse(options[19]);
if (options[20]) mapName.value = options[20];
}() }()
void function parseConfiguration() { void function parseConfiguration() {
@ -800,3 +805,14 @@ function toggleSaveReminder() {
saveReminder(); saveReminder();
} }
} }
function getFileName(dataType) {
const name = mapName.value;
const type = dataType ? dataType + " " : "";
const date = new Date();
const datFormatter = new Intl.DateTimeFormat("en", {month: "short", day: "numeric"});
const timeFormatter = new Intl.DateTimeFormat("ru", {hour: "numeric", minute: "numeric"});
const day = datFormatter.format(date).replace(" ", "");
const time = timeFormatter.format(date).replace(":", "-");
return name + " " + type + day + " " + time;
}

View file

@ -253,7 +253,7 @@ function editBiomes() {
const url = window.URL.createObjectURL(dataBlob); const url = window.URL.createObjectURL(dataBlob);
const link = document.createElement("a"); const link = document.createElement("a");
document.body.appendChild(link); document.body.appendChild(link);
link.download = "biomes_data" + Date.now() + ".csv"; link.download = getFileName("Biomes") + ".csv";
link.href = url; link.href = url;
link.click(); link.click();
window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000); window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000);

View file

@ -252,7 +252,7 @@ function editBurgs() {
} }
function downloadBurgsData() { function downloadBurgsData() {
let data = "Id,Burg,State,Culture,Population,Capital,Port,Longitude,Latitude,Elevation\n"; // headers let data = "Id,Burg,State,Culture,Population,Longitude,Latitude,Elevation ("+heightUnit.value+"),Capital,Port\n"; // headers
const valid = pack.burgs.filter(b => b.i && !b.removed); // all valid burgs const valid = pack.burgs.filter(b => b.i && !b.removed); // all valid burgs
valid.forEach(b => { valid.forEach(b => {
@ -261,20 +261,22 @@ function editBurgs() {
data += pack.states[b.state].name + ","; data += pack.states[b.state].name + ",";
data += pack.cultures[b.culture].name + ","; data += pack.cultures[b.culture].name + ",";
data += rn(b.population * populationRate.value * urbanization.value) + ","; data += rn(b.population * populationRate.value * urbanization.value) + ",";
data += b.capital ? "capital," : ",";
data += b.port ? "port," : ",";
// add geography data // add geography data
data += mapCoordinates.lonW + (b.x / graphWidth) * mapCoordinates.lonT + ","; data += mapCoordinates.lonW + (b.x / graphWidth) * mapCoordinates.lonT + ",";
data += mapCoordinates.latN - (b.y / graphHeight) * mapCoordinates.latT + ","; // this is inverted in QGIS otherwise data += mapCoordinates.latN - (b.y / graphHeight) * mapCoordinates.latT + ","; // this is inverted in QGIS otherwise
data += parseInt(getFriendlyHeight(pack.cells.h[b.cell])) + "\n"; data += parseInt(getHeight(pack.cells.h[b.cell])) + ",";
// add status data
data += b.capital ? "capital," : ",";
data += b.port ? "port\n" : "\n";
}); });
const dataBlob = new Blob([data], {type: "text/plain"}); const dataBlob = new Blob([data], {type: "text/plain"});
const url = window.URL.createObjectURL(dataBlob); const url = window.URL.createObjectURL(dataBlob);
const link = document.createElement("a"); const link = document.createElement("a");
document.body.appendChild(link); document.body.appendChild(link);
link.download = "burgs_data" + Date.now() + ".csv"; link.download = getFileName("Burgs") + ".csv";
link.href = url; link.href = url;
link.click(); link.click();
window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000); window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000);

View file

@ -477,7 +477,7 @@ function editCultures() {
const url = window.URL.createObjectURL(dataBlob); const url = window.URL.createObjectURL(dataBlob);
const link = document.createElement("a"); const link = document.createElement("a");
document.body.appendChild(link); document.body.appendChild(link);
link.download = "cultures_data" + Date.now() + ".csv"; link.download = getFileName("Cultures") + ".csv";
link.href = url; link.href = url;
link.click(); link.click();
window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000); window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000);

View file

@ -204,7 +204,7 @@ function editDiplomacy() {
const url = window.URL.createObjectURL(dataBlob); const url = window.URL.createObjectURL(dataBlob);
const link = document.createElement("a"); const link = document.createElement("a");
document.body.appendChild(link); document.body.appendChild(link);
link.download = "state_relations_history" + Date.now() + ".txt"; link.download = getFileName("Relations history") + ".txt";
link.href = url; link.href = url;
link.click(); link.click();
window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000); window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000);
@ -252,7 +252,7 @@ function editDiplomacy() {
const url = window.URL.createObjectURL(dataBlob); const url = window.URL.createObjectURL(dataBlob);
const link = document.createElement("a"); const link = document.createElement("a");
document.body.appendChild(link); document.body.appendChild(link);
link.download = "state_relations_data" + Date.now() + ".csv"; link.download = getFileName("Relations") + ".csv";
link.href = url; link.href = url;
link.click(); link.click();
window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000); window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000);

View file

@ -145,15 +145,18 @@ function updateCellInfo(point, i, g) {
// get user-friendly (real-world) height value from map data // get user-friendly (real-world) height value from map data
function getFriendlyHeight(p) { function getFriendlyHeight(p) {
const packH = pack.cells.h[findCell(p[0], p[1])];
const gridH = grid.cells.h[findGridCell(p[0], p[1])];
const h = packH < 20 ? gridH : packH;
return getHeight(h);
}
function getHeight(h) {
const unit = heightUnit.value; const unit = heightUnit.value;
let unitRatio = 3.281; // default calculations are in feet let unitRatio = 3.281; // default calculations are in feet
if (unit === "m") unitRatio = 1; // if meter if (unit === "m") unitRatio = 1; // if meter
else if (unit === "f") unitRatio = 0.5468; // if fathom else if (unit === "f") unitRatio = 0.5468; // if fathom
const packH = pack.cells.h[findCell(p[0], p[1])];
const gridH = grid.cells.h[findGridCell(p[0], p[1])];
const h = packH < 20 ? gridH : packH;
let height = -990; let height = -990;
if (h >= 20) height = Math.pow(h - 18, +heightExponentInput.value); if (h >= 20) height = Math.pow(h - 18, +heightExponentInput.value);
else if (h < 20 && h > 0) height = (h - 20) / h * 50; else if (h < 20 && h > 0) height = (h - 20) / h * 50;

View file

@ -1150,19 +1150,30 @@ function getHeight(h) {
document.body.insertBefore(canvas, optionsContainer); document.body.insertBefore(canvas, optionsContainer);
ctx.drawImage(img, 0, 0, svgWidth, svgHeight); ctx.drawImage(img, 0, 0, svgWidth, svgHeight);
// const imageData = ctx.getImageData(0, 0, svgWidth, svgHeight); const simplex = new SimplexNoise(); // SimplexNoise by Jonas Wagner
// for (let i=0; i < imageData.data.length; i+=4) { const noise = (nx, ny) => simplex.noise2D(nx, ny) / 2 + .5;
// const v = Math.min(rn(imageData.data[i] * gauss(1, .05, .9, 1.1, 3)), 255);
// imageData.data[i] = v; const imageData = ctx.getImageData(0, 0, svgWidth, svgHeight);
// imageData.data[i+1] = v; for (let i=0; i < imageData.data.length; i+=4) {
// imageData.data[i+2] = v; const v = imageData.data[i];
// } if (v < 51) {
// ctx.putImageData(imageData, 0, 0); // water
imageData.data[i] = imageData.data[i+1] = imageData.data[i+2] = 46;
continue;
}
const x = i / 4 % svgWidth, y = Math.floor(i / 4 / svgWidth);
const nx = x / svgWidth - .5, ny = y / svgHeight - .5;
const n = noise(4 * nx, 4 * ny) / 4 + noise(16 * nx, 16 * ny) / 16;
const nv = Math.max(Math.min((v + 255 * n) / 2, 255), 51);
imageData.data[i] = imageData.data[i+1] = imageData.data[i+2] = nv;
}
ctx.putImageData(imageData, 0, 0);
const imgBig = canvas.toDataURL("image/png"); const imgBig = canvas.toDataURL("image/png");
const link = document.createElement("a"); const link = document.createElement("a");
link.target = "_blank"; link.target = "_blank";
link.download = "heightmap_" + Date.now() + ".png"; link.download = getFileName("Heightmap") + ".png";
link.href = imgBig; link.href = imgBig;
document.body.appendChild(link); document.body.appendChild(link);
link.click(); link.click();

View file

@ -143,7 +143,7 @@ function editNamesbase() {
const dataBlob = new Blob([data.join("\r\n")], {type:"text/plain"}); const dataBlob = new Blob([data.join("\r\n")], {type:"text/plain"});
const url = window.URL.createObjectURL(dataBlob); const url = window.URL.createObjectURL(dataBlob);
const link = document.createElement("a"); const link = document.createElement("a");
link.download = "namesbase" + Date.now() + ".txt"; link.download = getFileName("Namesbase") + ".txt";
link.href = url; link.href = url;
link.click(); link.click();
} }

View file

@ -108,7 +108,7 @@ function editNotes(id, name) {
const dataBlob = new Blob([legendString],{type:"text/plain"}); const dataBlob = new Blob([legendString],{type:"text/plain"});
const url = window.URL.createObjectURL(dataBlob); const url = window.URL.createObjectURL(dataBlob);
const link = document.createElement("a"); const link = document.createElement("a");
link.download = "notes" + Date.now() + ".txt"; link.download = getFileName("Notes") + ".txt";
link.href = url; link.href = url;
link.click(); link.click();
} }

View file

@ -482,7 +482,7 @@ function editProvinces() {
const url = window.URL.createObjectURL(dataBlob); const url = window.URL.createObjectURL(dataBlob);
const link = document.createElement("a"); const link = document.createElement("a");
document.body.appendChild(link); document.body.appendChild(link);
link.download = "provinces_data" + Date.now() + ".csv"; link.download = getFileName("Provinces") + ".csv";
link.href = url; link.href = url;
link.click(); link.click();
window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000); window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000);

View file

@ -540,7 +540,7 @@ function editReligions() {
const url = window.URL.createObjectURL(dataBlob); const url = window.URL.createObjectURL(dataBlob);
const link = document.createElement("a"); const link = document.createElement("a");
document.body.appendChild(link); document.body.appendChild(link);
link.download = "religions_data" + Date.now() + ".csv"; link.download = getFileName("Religions") + ".csv";
link.href = url; link.href = url;
link.click(); link.click();
window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000); window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000);

View file

@ -692,7 +692,7 @@ function editStates() {
const url = window.URL.createObjectURL(dataBlob); const url = window.URL.createObjectURL(dataBlob);
const link = document.createElement("a"); const link = document.createElement("a");
document.body.appendChild(link); document.body.appendChild(link);
link.download = "states_data" + Date.now() + ".csv"; link.download = getFileName("States") + ".csv";
link.href = url; link.href = url;
link.click(); link.click();
window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000); window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000);

View file

@ -345,7 +345,7 @@ function editZones() {
const url = window.URL.createObjectURL(dataBlob); const url = window.URL.createObjectURL(dataBlob);
const link = document.createElement("a"); const link = document.createElement("a");
document.body.appendChild(link); document.body.appendChild(link);
link.download = "zones_data" + Date.now() + ".csv"; link.download = getFileName("Zones") + ".csv";
link.href = url; link.href = url;
link.click(); link.click();
window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000); window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000);