Add a map renderer
This commit is contained in:
parent
25bb565091
commit
9cdc1c48e4
3 changed files with 100 additions and 0 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,2 +1,3 @@
|
||||||
__pycache__
|
__pycache__
|
||||||
repos
|
repos
|
||||||
|
build
|
||||||
|
|
|
||||||
3
justfile
3
justfile
|
|
@ -15,3 +15,6 @@ run:
|
||||||
|
|
||||||
debug:
|
debug:
|
||||||
uv run python -m mudlib --debug
|
uv run python -m mudlib --debug
|
||||||
|
|
||||||
|
render:
|
||||||
|
uv run python scripts/render_map.py
|
||||||
|
|
|
||||||
96
scripts/render_map.py
Normal file
96
scripts/render_map.py
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
"""Render the full world map as an HTML page."""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import tomllib
|
||||||
|
import webbrowser
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
sys.path.insert(0, str(Path(__file__).parent.parent / "src"))
|
||||||
|
|
||||||
|
from mudlib.world.terrain import World
|
||||||
|
|
||||||
|
ROOT = Path(__file__).parent.parent
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
config_path = ROOT / "worlds" / "earth" / "config.toml"
|
||||||
|
with open(config_path, "rb") as f:
|
||||||
|
config = tomllib.load(f)
|
||||||
|
|
||||||
|
seed = config["world"]["seed"]
|
||||||
|
width = config["world"]["width"]
|
||||||
|
height = config["world"]["height"]
|
||||||
|
name = config["world"]["name"]
|
||||||
|
|
||||||
|
print(f"generating {name} ({width}x{height}, seed={seed})...")
|
||||||
|
world = World(seed=seed, width=width, height=height)
|
||||||
|
|
||||||
|
# encode terrain as compact string, one char per tile
|
||||||
|
rows = ["".join(row) for row in world.terrain]
|
||||||
|
terrain_data = "\\n".join(rows)
|
||||||
|
|
||||||
|
html = f"""<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>{name}</title>
|
||||||
|
<style>
|
||||||
|
body {{
|
||||||
|
margin: 0;
|
||||||
|
background: #111;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
min-height: 100vh;
|
||||||
|
}}
|
||||||
|
canvas {{
|
||||||
|
image-rendering: pixelated;
|
||||||
|
max-width: 100vmin;
|
||||||
|
max-height: 100vmin;
|
||||||
|
width: 100vmin;
|
||||||
|
height: 100vmin;
|
||||||
|
}}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<canvas id="map" width="{width}" height="{height}"></canvas>
|
||||||
|
<script>
|
||||||
|
const W = {width}, H = {height};
|
||||||
|
const terrain = "{terrain_data}";
|
||||||
|
const colors = {{
|
||||||
|
'~': [34, 68, 170],
|
||||||
|
':': [194, 178, 128],
|
||||||
|
'.': [34, 139, 34],
|
||||||
|
'T': [10, 95, 10],
|
||||||
|
'^': [102, 102, 102],
|
||||||
|
}};
|
||||||
|
const canvas = document.getElementById('map');
|
||||||
|
const ctx = canvas.getContext('2d');
|
||||||
|
const img = ctx.createImageData(W, H);
|
||||||
|
const d = img.data;
|
||||||
|
const rows = terrain.split('\\n');
|
||||||
|
for (let y = 0; y < H; y++) {{
|
||||||
|
const row = rows[y];
|
||||||
|
for (let x = 0; x < W; x++) {{
|
||||||
|
const c = colors[row[x]] || [255, 0, 255];
|
||||||
|
const i = (y * W + x) * 4;
|
||||||
|
d[i] = c[0];
|
||||||
|
d[i+1] = c[1];
|
||||||
|
d[i+2] = c[2];
|
||||||
|
d[i+3] = 255;
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
ctx.putImageData(img, 0, 0);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>"""
|
||||||
|
|
||||||
|
out_path = ROOT / "build" / "map.html"
|
||||||
|
out_path.parent.mkdir(exist_ok=True)
|
||||||
|
out_path.write_text(html)
|
||||||
|
print(f"wrote {out_path}")
|
||||||
|
webbrowser.open(f"file://{out_path.resolve()}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Loading…
Reference in a new issue