mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2026-02-05 01:51:23 +01:00
refactor: Remove river-generator.js reference and add biomes module
This commit is contained in:
parent
2ba8bd12b8
commit
49e7e5c533
3 changed files with 54 additions and 34 deletions
|
|
@ -8470,7 +8470,6 @@
|
||||||
<script defer src="config/heightmap-templates.js"></script>
|
<script defer src="config/heightmap-templates.js"></script>
|
||||||
<script defer src="config/precreated-heightmaps.js"></script>
|
<script defer src="config/precreated-heightmaps.js"></script>
|
||||||
<script defer src="modules/lakes.js?v=1.99.00"></script>
|
<script defer src="modules/lakes.js?v=1.99.00"></script>
|
||||||
<script defer src="modules/biomes.js?v=1.99.00"></script>
|
|
||||||
<script defer src="modules/names-generator.js?v=1.106.0"></script>
|
<script defer src="modules/names-generator.js?v=1.106.0"></script>
|
||||||
<script defer src="modules/cultures-generator.js?v=1.106.0"></script>
|
<script defer src="modules/cultures-generator.js?v=1.106.0"></script>
|
||||||
<script defer src="modules/burgs-generator.js?v=1.109.5"></script>
|
<script defer src="modules/burgs-generator.js?v=1.109.5"></script>
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,30 @@
|
||||||
"use strict";
|
import { range, mean } from "d3";
|
||||||
|
import { rn } from "../utils";
|
||||||
|
|
||||||
window.Biomes = (function () {
|
declare global {
|
||||||
const MIN_LAND_HEIGHT = 20;
|
var Biomes: BiomesModule;
|
||||||
|
|
||||||
const getDefault = () => {
|
var pack: any;
|
||||||
const name = [
|
var grid: any;
|
||||||
|
var TIME: boolean;
|
||||||
|
|
||||||
|
var biomesData: {
|
||||||
|
i: number[];
|
||||||
|
name: string[];
|
||||||
|
color: string[];
|
||||||
|
biomesMartix: Uint8Array[];
|
||||||
|
habitability: number[];
|
||||||
|
iconsDensity: number[];
|
||||||
|
icons: string[][];
|
||||||
|
cost: number[];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class BiomesModule {
|
||||||
|
private MIN_LAND_HEIGHT = 20;
|
||||||
|
|
||||||
|
getDefault() {
|
||||||
|
const name: string[] = [
|
||||||
"Marine",
|
"Marine",
|
||||||
"Hot desert",
|
"Hot desert",
|
||||||
"Cold desert",
|
"Cold desert",
|
||||||
|
|
@ -20,7 +40,7 @@ window.Biomes = (function () {
|
||||||
"Wetland"
|
"Wetland"
|
||||||
];
|
];
|
||||||
|
|
||||||
const color = [
|
const color: string[] = [
|
||||||
"#466eab",
|
"#466eab",
|
||||||
"#fbe79f",
|
"#fbe79f",
|
||||||
"#b5b887",
|
"#b5b887",
|
||||||
|
|
@ -35,9 +55,9 @@ window.Biomes = (function () {
|
||||||
"#d5e7eb",
|
"#d5e7eb",
|
||||||
"#0b9131"
|
"#0b9131"
|
||||||
];
|
];
|
||||||
const habitability = [0, 4, 10, 22, 30, 50, 100, 80, 90, 12, 4, 0, 12];
|
const habitability: number[] = [0, 4, 10, 22, 30, 50, 100, 80, 90, 12, 4, 0, 12];
|
||||||
const iconsDensity = [0, 3, 2, 120, 120, 120, 120, 150, 150, 100, 5, 0, 250];
|
const iconsDensity: number[] = [0, 3, 2, 120, 120, 120, 120, 150, 150, 100, 5, 0, 250];
|
||||||
const icons = [
|
const icons: Array<{[key: string]: number}> = [
|
||||||
{},
|
{},
|
||||||
{dune: 3, cactus: 6, deadTree: 1},
|
{dune: 3, cactus: 6, deadTree: 1},
|
||||||
{dune: 9, deadTree: 1},
|
{dune: 9, deadTree: 1},
|
||||||
|
|
@ -52,8 +72,8 @@ window.Biomes = (function () {
|
||||||
{},
|
{},
|
||||||
{swamp: 1}
|
{swamp: 1}
|
||||||
];
|
];
|
||||||
const cost = [10, 200, 150, 60, 50, 70, 70, 80, 90, 200, 1000, 5000, 150]; // biome movement cost
|
const cost: number[] = [10, 200, 150, 60, 50, 70, 70, 80, 90, 200, 1000, 5000, 150]; // biome movement cost
|
||||||
const biomesMartix = [
|
const biomesMartix: Uint8Array[] = [
|
||||||
// hot ↔ cold [>19°C; <-4°C]; dry ↕ wet
|
// hot ↔ cold [>19°C; <-4°C]; dry ↕ wet
|
||||||
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, 10]),
|
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, 10]),
|
||||||
new Uint8Array([3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 9, 9, 9, 10, 10, 10]),
|
new Uint8Array([3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 9, 9, 9, 10, 10, 10]),
|
||||||
|
|
@ -63,53 +83,53 @@ window.Biomes = (function () {
|
||||||
];
|
];
|
||||||
|
|
||||||
// parse icons weighted array into a simple array
|
// parse icons weighted array into a simple array
|
||||||
|
const parsedIcons: string[][] = [];
|
||||||
for (let i = 0; i < icons.length; i++) {
|
for (let i = 0; i < icons.length; i++) {
|
||||||
const parsed = [];
|
const parsed: string[] = [];
|
||||||
for (const icon in icons[i]) {
|
for (const icon in icons[i]) {
|
||||||
for (let j = 0; j < icons[i][icon]; j++) {
|
for (let j = 0; j < icons[i][icon]; j++) {
|
||||||
parsed.push(icon);
|
parsed.push(icon);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
icons[i] = parsed;
|
parsedIcons[i] = parsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {i: d3.range(0, name.length), name, color, biomesMartix, habitability, iconsDensity, icons, cost};
|
return {i: range(0, name.length), name, color, biomesMartix, habitability, iconsDensity, icons: parsedIcons, cost};
|
||||||
};
|
};
|
||||||
|
|
||||||
// assign biome id for each cell
|
define() {
|
||||||
function define() {
|
|
||||||
TIME && console.time("defineBiomes");
|
TIME && console.time("defineBiomes");
|
||||||
|
|
||||||
const {fl: flux, r: riverIds, h: heights, c: neighbors, g: gridReference} = pack.cells;
|
const {fl: flux, r: riverIds, h: heights, c: neighbors, g: gridReference} = pack.cells;
|
||||||
const {temp, prec} = grid.cells;
|
const {temp, prec} = grid.cells;
|
||||||
pack.cells.biome = new Uint8Array(pack.cells.i.length); // biomes array
|
pack.cells.biome = new Uint8Array(pack.cells.i.length); // biomes array
|
||||||
|
|
||||||
for (let cellId = 0; cellId < heights.length; cellId++) {
|
const calculateMoisture = (cellId: number) => {
|
||||||
const height = heights[cellId];
|
|
||||||
const moisture = height < MIN_LAND_HEIGHT ? 0 : calculateMoisture(cellId);
|
|
||||||
const temperature = temp[gridReference[cellId]];
|
|
||||||
pack.cells.biome[cellId] = getId(moisture, temperature, height, Boolean(riverIds[cellId]));
|
|
||||||
}
|
|
||||||
|
|
||||||
function calculateMoisture(cellId) {
|
|
||||||
let moisture = prec[gridReference[cellId]];
|
let moisture = prec[gridReference[cellId]];
|
||||||
if (riverIds[cellId]) moisture += Math.max(flux[cellId] / 10, 2);
|
if (riverIds[cellId]) moisture += Math.max(flux[cellId] / 10, 2);
|
||||||
|
|
||||||
const moistAround = neighbors[cellId]
|
const moistAround = neighbors[cellId]
|
||||||
.filter(neibCellId => heights[neibCellId] >= MIN_LAND_HEIGHT)
|
.filter((neibCellId: number) => heights[neibCellId] >= this.MIN_LAND_HEIGHT)
|
||||||
.map(c => prec[gridReference[c]])
|
.map((c: number) => prec[gridReference[c]])
|
||||||
.concat([moisture]);
|
.concat([moisture]);
|
||||||
return rn(4 + d3.mean(moistAround));
|
return rn(4 + (mean(moistAround) as number));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let cellId = 0; cellId < heights.length; cellId++) {
|
||||||
|
const height = heights[cellId];
|
||||||
|
const moisture = height < this.MIN_LAND_HEIGHT ? 0 : calculateMoisture(cellId);
|
||||||
|
const temperature = temp[gridReference[cellId]];
|
||||||
|
pack.cells.biome[cellId] = this.getId(moisture, temperature, height, Boolean(riverIds[cellId]));
|
||||||
}
|
}
|
||||||
|
|
||||||
TIME && console.timeEnd("defineBiomes");
|
TIME && console.timeEnd("defineBiomes");
|
||||||
}
|
}
|
||||||
|
|
||||||
function getId(moisture, temperature, height, hasRiver) {
|
getId(moisture: number, temperature: number, height: number, hasRiver: boolean) {
|
||||||
if (height < 20) return 0; // all water cells: marine biome
|
if (height < 20) return 0; // all water cells: marine biome
|
||||||
if (temperature < -5) return 11; // too cold: permafrost biome
|
if (temperature < -5) return 11; // too cold: permafrost biome
|
||||||
if (temperature >= 25 && !hasRiver && moisture < 8) return 1; // too hot and dry: hot desert biome
|
if (temperature >= 25 && !hasRiver && moisture < 8) return 1; // too hot and dry: hot desert biome
|
||||||
if (isWetland(moisture, temperature, height)) return 12; // too wet: wetland biome
|
if (this.isWetland(moisture, temperature, height)) return 12; // too wet: wetland biome
|
||||||
|
|
||||||
// in other cases use biome matrix
|
// in other cases use biome matrix
|
||||||
const moistureBand = Math.min((moisture / 5) | 0, 4); // [0-4]
|
const moistureBand = Math.min((moisture / 5) | 0, 4); // [0-4]
|
||||||
|
|
@ -117,12 +137,12 @@ window.Biomes = (function () {
|
||||||
return biomesData.biomesMartix[moistureBand][temperatureBand];
|
return biomesData.biomesMartix[moistureBand][temperatureBand];
|
||||||
}
|
}
|
||||||
|
|
||||||
function isWetland(moisture, temperature, height) {
|
private isWetland(moisture: number, temperature: number, height: number) {
|
||||||
if (temperature <= -2) return false; // too cold
|
if (temperature <= -2) return false; // too cold
|
||||||
if (moisture > 40 && height < 25) return true; // near coast
|
if (moisture > 40 && height < 25) return true; // near coast
|
||||||
if (moisture > 24 && height > 24 && height < 60) return true; // off coast
|
if (moisture > 24 && height > 24 && height < 60) return true; // off coast
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {getDefault, define, getId};
|
window.Biomes = new BiomesModule();
|
||||||
})();
|
|
||||||
|
|
@ -2,4 +2,5 @@ import "./voronoi";
|
||||||
import "./heightmap-generator";
|
import "./heightmap-generator";
|
||||||
import "./features";
|
import "./features";
|
||||||
import "./ocean-layers";
|
import "./ocean-layers";
|
||||||
import "./river-generator";
|
import "./river-generator";
|
||||||
|
import "./biomes"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue