Reorganize assets; switch the HUD to the Micro Chat font

Source packs move to assets/packs (untouched), maps to assets/maps, and the
palette/sketch leftovers from the 8-bit era go. tools/mkfont.py repacks
VEXED's Micro Chat sheet (8-column grid, 8x10 cells) into the CP437 atlas
layout the font loader already reads, cropped to 8x9 so the HUD can use an
8 px line height. The CGA atlas is dropped in its favor.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-20 19:47:33 +02:00
co-authored by Claude Opus 5
parent bb12f095d8
commit 335962800f
111 changed files with 528 additions and 546 deletions
+68
View File
@@ -0,0 +1,68 @@
#!/usr/bin/env python3
"""Repack VEXED's Micro Chat sheet into the game's CP437 atlas layout.
Source: assets/fonts/Micro-Chat-All/Micro-Chat.png — an 8-column grid with 1 px
gray grid lines, 8×10 cells, black glyphs on transparent; the glyph order comes
from the "Supported Glyphs (PNG Order)" block in Micro-Chat-Info.md.
Output: a 32×8-cell atlas (codepoint = index, like the CGA sheet) with white glyphs
on opaque black, so game/src/font.rs loads it unchanged. Cells are cropped to source
rows 1..9 (umlaut dots down to descenders): 8×9 px.
python3 tools/mkfont.py
"""
from PIL import Image
SRC = "assets/fonts/Micro-Chat-All/Micro-Chat.png"
INFO = "assets/fonts/Micro-Chat-All/Micro-Chat-Info.md"
OUT = "assets/fonts/micro-chat-8x9.png"
CELL_W, CELL_H = 8, 10 # source cell
STRIDE_X, STRIDE_Y = 9, 11 # cell + grid line
CROP_TOP, OUT_H = 1, 9 # keep source rows 1..9
# Same table as font::cp437 — the accented slots the game may ask for.
CP437 = {
'Ç': 128, 'ü': 129, 'é': 130, 'ä': 132, 'à': 133, 'å': 134, 'ç': 135,
'ë': 137, 'è': 138, 'ï': 139, 'î': 140, 'ì': 141, 'Ä': 142, 'Å': 143,
'É': 144, 'ö': 148, 'ò': 149, 'û': 150, 'ù': 151, 'Ö': 153, 'Ü': 154,
'á': 160, 'í': 161, 'ó': 162, 'ú': 163, 'ñ': 164, 'Ñ': 165, 'ß': 225,
}
CP437.update({chr(c): c for c in range(32, 127)})
def source_cells():
block = open(INFO, encoding="utf-8").read()
block = block.split("## Supported Glyphs (PNG Order)")[1].split("``")[1]
cells = {}
for row, line in enumerate(block.strip("\n").split("\n")):
for col, ch in enumerate(line):
cells[ch] = (col, row)
return cells
def main():
src = Image.open(SRC).convert("RGBA")
cells = source_cells()
out = Image.new("RGB", (32 * CELL_W, 8 * OUT_H), (0, 0, 0))
missing = []
for ch, code in sorted(CP437.items(), key=lambda kv: kv[1]):
if ch not in cells:
missing.append(ch)
continue
if ch == " ":
continue # the sheet marks the space cell with a bar; ours must be blank
col, row = cells[ch]
x0, y0 = 1 + col * STRIDE_X, 1 + row * STRIDE_Y + CROP_TOP
for y in range(OUT_H):
for x in range(CELL_W):
r, g, b, a = src.getpixel((x0 + x, y0 + y))
if a > 0 and r < 100:
out.putpixel(((code % 32) * CELL_W + x, (code // 32) * OUT_H + y), (255, 255, 255))
out.save(OUT)
print(f"wrote {OUT}; missing: {''.join(missing) or '-'}")
if __name__ == "__main__":
main()