crocparty/pytools/mapdata.py
2024-02-26 19:51:26 -08:00

90 lines
2.8 KiB
Python

import sys
import json
import shared
TEMPLATE = """
// generated code! be nice
#include "sys/sys.h"
sys_i32 {{map_name}}_player_start_x = {{player_start.0}};
sys_i32 {{map_name}}_player_start_y = {{player_start.1}};
sys_maptile {{map_name}}_data[{{width * height}}] = { {{ tiles|join(",") }} };
sys_map {{map_name}} = {
.tiles={{map_name}}_data,
.width={{width}},
.height={{height}},
};
""".lstrip()
def main(map_name, fname_ldtk, fname_c):
width, height, tiles, player_start = load_mapdata(fname_ldtk)
with open(fname_c, "wt") as output:
output.write(
shared.templates.from_string(TEMPLATE).render(
map_name=map_name,
player_start=player_start,
tiles=tiles,
width=width,
height=height,
)
)
def load_mapdata(fname_ldtk):
sparse_tiles = {}
player_start_xy = None
with open(fname_ldtk, "rt") as f:
data = json.load(f)
for level in data["levels"]:
level_x = level["worldX"] // 8
level_y = level["worldY"] // 8
for layer in level["layerInstances"]:
w = layer["__cWid"]
h = layer["__cHei"]
if layer["__identifier"] == "vague":
# for right now I use the vague layer to assign tiles
for x, y, ix in annot_xy(layer["intGridCsv"], w, h):
if ix == 0:
continue
sparse_tiles[level_x + x, level_y + y] = ix
if layer["__identifier"] == "entities":
for e in layer["entityInstances"]:
x, y = e["__grid"]
player_start_xy = (level_x + x, level_y + y)
assert player_start_xy is not None, "player start not found"
x_min = 0
y_min = 0
assert not any(x for (x, _) in sparse_tiles if x < x_min), "level can't be left of (0, 0)"
assert not any(y for (_, y) in sparse_tiles if y < y_min), "level can't be up from (0, 0)"
width = max(x for (x, _) in sparse_tiles) + 1
height = max(y for (_, y) in sparse_tiles) + 1
dense_tiles = []
for y in range(height):
for x in range(width):
k = (x, y)
if k in sparse_tiles:
dense_tiles.append(sparse_tiles[k])
else:
dense_tiles.append(0)
return width, height, dense_tiles, player_start_xy
def annot_xy(lst, w, h):
assert len(lst) == w * h
for y in range(h):
for x in range(w):
yield x, y, lst[y * w + x]
if __name__ == "__main__":
assert len(sys.argv) == 4, \
"there must be three args (map name, src ldtk, out c)"
main(sys.argv[1], sys.argv[2], sys.argv[3])