Added thumbnail generation to the TerrainMapGenerator script. (#292)
Added functions to TerrainMapGenerator to create a bitmap from the Minimap Terrain array with the colors being identical to those rendered in game, with the additional change of setting the Alpha of all water to 0. Calls added to generateTerrainMaps to actually generate the thumbnail PNGs, Revision to src\client\utilities\maps.ts to reflect that the images pulled into the UI should be those ending in 'Thumb.png,' I've tested by launching the game and starting a few matches. hile I'd hoped that using the minimaps as the basis for the thumbnails would speed things up I think the actual bottleneck is the writing to the file system. Below is a screenshot showing these thumbnails in the UI.     Finally I will say that while the code additions work, given my novice status with typescript and asynch calls these changes may benefit more from review and a little critical feedback before they're ready to merge.
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 600 KiB |
|
After Width: | Height: | Size: 596 KiB |
|
After Width: | Height: | Size: 383 KiB |
|
After Width: | Height: | Size: 517 KiB |
|
After Width: | Height: | Size: 921 KiB |
|
After Width: | Height: | Size: 373 KiB |
|
After Width: | Height: | Size: 801 KiB |
|
After Width: | Height: | Size: 768 KiB |
|
After Width: | Height: | Size: 142 KiB |
|
After Width: | Height: | Size: 276 KiB |
|
After Width: | Height: | Size: 357 KiB |
@@ -1,15 +1,15 @@
|
||||
import world from "../../../resources/maps/WorldMap.png";
|
||||
import oceania from "../../../resources/maps/Oceania.png";
|
||||
import europe from "../../../resources/maps/Europe.png";
|
||||
import mena from "../../../resources/maps/Mena.png";
|
||||
import northAmerica from "../../../resources/maps/NorthAmerica.png";
|
||||
import southAmerica from "../../../resources/maps/SouthAmerica.png";
|
||||
import blackSea from "../../../resources/maps/BlackSea.png";
|
||||
import africa from "../../../resources/maps/Africa.png";
|
||||
import asia from "../../../resources/maps/Asia.png";
|
||||
import mars from "../../../resources/maps/Mars.png";
|
||||
import britannia from "../../../resources/maps/Britannia.png";
|
||||
import gatewayToTheAtlantic from "../../../resources/maps/GatewayToTheAtlantic.png";
|
||||
import world from "../../../resources/maps/WorldMapThumb.png";
|
||||
import oceania from "../../../resources/maps/OceaniaThumb.png";
|
||||
import europe from "../../../resources/maps/EuropeThumb.png";
|
||||
import mena from "../../../resources/maps/MenaThumb.png";
|
||||
import northAmerica from "../../../resources/maps/NorthAmericaThumb.png";
|
||||
import southAmerica from "../../../resources/maps/SouthAmericaThumb.png";
|
||||
import blackSea from "../../../resources/maps/BlackSeaThumb.png";
|
||||
import africa from "../../../resources/maps/AfricaThumb.png";
|
||||
import asia from "../../../resources/maps/AsiaThumb.png";
|
||||
import mars from "../../../resources/maps/MarsThumb.png";
|
||||
import britannia from "../../../resources/maps/BritanniaThumb.png";
|
||||
import gatewayToTheAtlantic from "../../../resources/maps/GatewayToTheAtlanticThumb.png";
|
||||
|
||||
import { GameMapType } from "../../core/game/Game";
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { decodePNGFromStream } from "pureimage";
|
||||
import path from "path";
|
||||
import fs from "fs/promises";
|
||||
import { createReadStream } from "fs";
|
||||
import { decodePNGFromStream, Bitmap } from "pureimage";
|
||||
//import path from "path";
|
||||
//import fs from "fs/promises";
|
||||
//import { createReadStream } from "fs";
|
||||
import { Readable } from "stream";
|
||||
|
||||
const min_island_size = 30;
|
||||
@@ -26,7 +26,7 @@ class Terrain {
|
||||
export async function generateMap(
|
||||
imageBuffer: Buffer,
|
||||
removeSmall = true,
|
||||
): Promise<{ map: Uint8Array; miniMap: Uint8Array }> {
|
||||
): Promise<{ map: Uint8Array; miniMap: Uint8Array; thumb: Bitmap }> {
|
||||
const stream = Readable.from(imageBuffer);
|
||||
const img = await decodePNGFromStream(stream);
|
||||
|
||||
@@ -66,10 +66,12 @@ export async function generateMap(
|
||||
processOcean(terrain);
|
||||
|
||||
const miniTerrain = await createMiniMap(terrain);
|
||||
const thumb = await createMapThumbnail(miniTerrain);
|
||||
|
||||
return {
|
||||
map: packTerrain(terrain),
|
||||
miniMap: packTerrain(miniTerrain),
|
||||
thumb: thumb,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -326,3 +328,69 @@ function getNeighborCoords(x: number, y: number, map: Terrain[][]): Coord[] {
|
||||
}
|
||||
return coords;
|
||||
}
|
||||
|
||||
async function createMapThumbnail(map: Terrain[][]): Promise<Bitmap> {
|
||||
console.log("creating thumbnail");
|
||||
const bitmap = new Bitmap(map.length, map[0].length);
|
||||
for (let x = 0; x < bitmap.width; x++) {
|
||||
for (let y = 0; y < bitmap.height; y++) {
|
||||
const rgba = getThumbnailColor(map[x][y]);
|
||||
bitmap.setPixelRGBA_i(x, y, rgba.r, rgba.g, rgba.b, rgba.a);
|
||||
}
|
||||
}
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
function getThumbnailColor(t: Terrain): {
|
||||
r: number;
|
||||
g: number;
|
||||
b: number;
|
||||
a: number;
|
||||
} {
|
||||
if (t.type === TerrainType.Water) {
|
||||
//shoreline water
|
||||
if (t.shoreline) return { r: 100, g: 143, b: 255, a: 0 };
|
||||
//all other water
|
||||
const waterAdjRGB: number = 11 - Math.min(t.magnitude / 2, 10) - 10;
|
||||
return {
|
||||
r: Math.max(70 + waterAdjRGB, 0),
|
||||
g: Math.max(132 + waterAdjRGB, 0),
|
||||
b: Math.max(180 + waterAdjRGB, 0),
|
||||
a: 0,
|
||||
};
|
||||
}
|
||||
//shoreline land
|
||||
if (t.shoreline) {
|
||||
return { r: 204, g: 203, b: 158, a: 255 };
|
||||
}
|
||||
let adjRGB: number;
|
||||
switch (true) {
|
||||
//plains
|
||||
case t.magnitude < 10:
|
||||
adjRGB = 220 - 2 * t.magnitude;
|
||||
return {
|
||||
r: 190,
|
||||
g: adjRGB,
|
||||
b: 138,
|
||||
a: 255,
|
||||
};
|
||||
//highlands
|
||||
case t.magnitude < 20:
|
||||
adjRGB = 2 * t.magnitude;
|
||||
return {
|
||||
r: 200 + adjRGB,
|
||||
g: 183 + adjRGB,
|
||||
b: 138 + adjRGB,
|
||||
a: 255,
|
||||
};
|
||||
//mountains
|
||||
case t.magnitude >= 20:
|
||||
adjRGB = Math.floor(230 + t.magnitude / 2);
|
||||
return {
|
||||
r: adjRGB,
|
||||
g: adjRGB,
|
||||
b: adjRGB,
|
||||
a: 255,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { encodePNGToStream } from "pureimage";
|
||||
import { generateMap } from "./TerrainMapGenerator.js";
|
||||
import path from "path";
|
||||
import fs from "fs/promises";
|
||||
import { WriteStream, createWriteStream } from "fs";
|
||||
|
||||
const maps = [
|
||||
"Africa",
|
||||
@@ -13,6 +15,7 @@ const maps = [
|
||||
"Oceania",
|
||||
"NorthAmerica",
|
||||
"SouthAmerica",
|
||||
"Britannia",
|
||||
"GatewayToTheAtlantic",
|
||||
];
|
||||
|
||||
@@ -26,7 +29,7 @@ async function loadTerrainMaps() {
|
||||
map + ".png",
|
||||
);
|
||||
const imageBuffer = await fs.readFile(mapPath);
|
||||
const { map: mainMap, miniMap } = await generateMap(imageBuffer);
|
||||
const { map: mainMap, miniMap, thumb } = await generateMap(imageBuffer);
|
||||
|
||||
const outputPath = path.join(
|
||||
process.cwd(),
|
||||
@@ -40,10 +43,21 @@ async function loadTerrainMaps() {
|
||||
"maps",
|
||||
map + "Mini.bin",
|
||||
);
|
||||
const thumbOutputPath = path.join(
|
||||
process.cwd(),
|
||||
"resources",
|
||||
"maps",
|
||||
map + "Thumb.png",
|
||||
);
|
||||
const thumbOutStream: WriteStream = createWriteStream(
|
||||
thumbOutputPath,
|
||||
"binary",
|
||||
);
|
||||
|
||||
await Promise.all([
|
||||
fs.writeFile(outputPath, mainMap),
|
||||
fs.writeFile(miniOutputPath, miniMap),
|
||||
encodePNGToStream(thumb, thumbOutStream),
|
||||
]);
|
||||
}),
|
||||
);
|
||||
|
||||