mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-03 05:30:45 +00:00
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.
This commit is contained in:
@@ -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),
|
||||
]);
|
||||
}),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user