71 lines
2.4 KiB
JavaScript
71 lines
2.4 KiB
JavaScript
import { readFile, writeFile } from 'fs/promises';
|
|
import * as process from 'process';
|
|
|
|
import canvas from 'canvas';
|
|
import minimist from 'minimist';
|
|
|
|
import * as format_c2g from '../format-c2g.js';
|
|
import { infer_tileset_from_image } from '../tileset.js';
|
|
import { NodeCanvasRenderer } from './lib.js';
|
|
|
|
|
|
const USAGE = `\
|
|
Usage: render.mjs [OPTION]... LEVELFILE OUTFILE
|
|
Renders the level contained in LEVELFILE to a PNG and saves it to OUTFILE.
|
|
|
|
Arguments:
|
|
-t FILE path to a tileset to use
|
|
-e render in editor mode: use the revealed forms of tiles and
|
|
show facing directions
|
|
-l NUM choose the level number to render, if LEVELFILE is a pack
|
|
[default: 1]
|
|
-r REGION specify the region to render; see below
|
|
|
|
REGION may be one of:
|
|
initial an area the size of the level's viewport, centered on the
|
|
player's initial position
|
|
all the entire level
|
|
WxH an area W by H, centered on the player's initial position
|
|
...etc...
|
|
`;
|
|
async function main() {
|
|
let args = minimist(process.argv.slice(2), {
|
|
alias: {
|
|
tileset: ['t'],
|
|
},
|
|
});
|
|
// assert _.length is 2
|
|
let [pack_path, dest_path] = args._;
|
|
|
|
// TODO i need a more consistent and coherent way to turn a path into a level pack, currently
|
|
// this is only a single c2m
|
|
let pack_data = await readFile(pack_path);
|
|
let stored_level = format_c2g.parse_level(pack_data.buffer);
|
|
|
|
let img = await canvas.loadImage(args.tileset ?? 'tileset-lexy.png');
|
|
let tileset = infer_tileset_from_image(img);
|
|
let renderer = new NodeCanvasRenderer(tileset);
|
|
renderer.set_level(stored_level);
|
|
|
|
let i = stored_level.linear_cells.findIndex(cell => cell.some(tile => tile && tile.type.is_real_player));
|
|
if (i < 0) {
|
|
console.log("???");
|
|
process.stderr.write("error: no players in this level\n");
|
|
process.exit(1);
|
|
}
|
|
|
|
let [x, y] = stored_level.scalar_to_coords(i);
|
|
let w = stored_level.viewport_size;
|
|
let h = w;
|
|
|
|
// TODO this is probably duplicated from the renderer, and could also be reused in the editor
|
|
// TODO handle a map smaller than the viewport
|
|
let x0 = Math.max(0, x - w / 2);
|
|
let y0 = Math.max(0, y - h / 2);
|
|
renderer.draw_static_region(x0, y0, x0 + w, y0 + h);
|
|
|
|
await writeFile(dest_path, renderer.canvas.toBuffer());
|
|
}
|
|
|
|
main();
|