aboutsummaryrefslogtreecommitdiff
path: root/tools/map.py
diff options
context:
space:
mode:
authorJuan J. Martinez <jjm@usebox.net>2021-05-03 08:21:10 +0100
committerJuan J. Martinez <jjm@usebox.net>2021-05-03 10:00:00 +0100
commitc3b0fa04a663fe233765b83d3be41a42aa08c25d (patch)
tree0befda349001ef6ce306b39378f9c70ad917363e /tools/map.py
downloadreturn-of-traxtor-cpc-main.tar.gz
return-of-traxtor-cpc-main.zip
Initial import for public releaseHEADmain
Diffstat (limited to 'tools/map.py')
-rwxr-xr-xtools/map.py162
1 files changed, 162 insertions, 0 deletions
diff --git a/tools/map.py b/tools/map.py
new file mode 100755
index 0000000..e5d3199
--- /dev/null
+++ b/tools/map.py
@@ -0,0 +1,162 @@
+#!/usr/bin/env python
+
+__version__ = "1.0"
+
+import sys
+from argparse import ArgumentParser
+import json
+import subprocess
+from collections import defaultdict
+
+DEF_ROOM_WIDTH = 20
+DEF_ROOM_HEIGHT = 10
+
+def find_name(data, name):
+ for item in data:
+ if item.get("name").lower() == name.lower():
+ return item
+ raise ValueError("%r not found" % name)
+
+def main():
+
+ parser = ArgumentParser(description="Map importer",
+ epilog="Copyright (C) 2015 Juan J Martinez <jjm@usebox.net>",
+ )
+
+ parser.add_argument("--version", action="version", version="%(prog)s " + __version__)
+ parser.add_argument("--room-width", dest="rw", default=DEF_ROOM_WIDTH, type=int,
+ help="room width (default: %s)" % DEF_ROOM_WIDTH)
+ parser.add_argument("--room-height", dest="rh", default=DEF_ROOM_HEIGHT, type=int,
+ help="room height (default: %s)" % DEF_ROOM_HEIGHT)
+ parser.add_argument("-b", dest="bin", action="store_true",
+ help="output binary data (default: C code)")
+ parser.add_argument("--ucl", dest="ucl", action="store_true",
+ help="UCL compress (requires ucl binary in the path)")
+ parser.add_argument("map_json", help="Map to import")
+ parser.add_argument("id", help="variable name")
+
+ args = parser.parse_args()
+
+ with open(args.map_json, "rt") as fd:
+ data = json.load(fd)
+
+ mh = data.get("height", 0)
+ mw = data.get("width", 0)
+
+ if mh < args.rh or mh % args.rh:
+ parser.error("Map size in not multiple of the room size")
+ if mw < args.rw or mw % args.rw:
+ parser.error("Map size in not multiple of the room size")
+
+ tilewidth = data["tilewidth"]
+ tileheight = data["tileheight"]
+
+ tile_layer = find_name(data["layers"], "Map")["data"]
+
+ def_tileset = find_name(data["tilesets"], "default")
+ tileprops = def_tileset.get("tileproperties", {})
+ firstgid = def_tileset.get("firstgid")
+
+ out = []
+ for y in range(0, mh, args.rh):
+ for x in range(0, mw, args.rw):
+ current = []
+ for j in range(args.rh):
+ for i in range(args.rw / 2):
+ a = (tile_layer[x + (i * 2) + (y + j) * mw] - firstgid) & 0b111
+ if str(a) in tileprops and tileprops[str(a)].get("blocked"):
+ a |= 0b1000
+
+ b = (tile_layer[x + (i * 2) + 1 + (y + j) * mw] - firstgid) & 0b111
+ if str(b) in tileprops and tileprops[str(b)].get("blocked"):
+ b |= 0b1000
+
+ current.append((a << 4) | b)
+ out.append(current)
+
+ if args.ucl:
+ compressed = []
+ for block in out:
+ p = subprocess.Popen(["ucl",], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+ output, err = p.communicate(bytearray(block))
+ compressed.append([ord(b) for b in output])
+ out = compressed
+
+ if args.bin:
+ sys.stdout.write(bytearray(out))
+ return
+
+ print("#define WMAPS %d" % (mw // args.rw))
+
+ if args.ucl:
+ data_out = ""
+ for i, block in enumerate(out):
+ data_out_part = ""
+ for part in range(0, len(block), args.rw // 2):
+ if data_out_part:
+ data_out_part += ",\n"
+ data_out_part += ', '.join(["0x%02x" % b for b in block[part: part + args.rw // 2]])
+ data_out += "const unsigned char %s_%d[%d] = {\n" % (args.id, i, len(block))
+ data_out += data_out_part + "\n};\n"
+
+ data_out += "const unsigned char *%s[%d] = { " % (args.id, len(out))
+ data_out += ', '.join(["%s_%d" % (args.id, i) for i in range(len(out))])
+ data_out += " };\n"
+ print(data_out)
+
+ else:
+ data_out = ""
+ for block in out:
+ if data_out:
+ data_out += ",\n"
+ data_out += "{"
+ for part in range(0, len(block), args.rw // 2):
+ if data_out and data_out[-1] != "{":
+ data_out += ",\n"
+ data_out += ', '.join(["0x%02x" % b for b in block[part: part + args.rw // 2]])
+ data_out += "}\n"
+
+ print("const unsigned char %s[%d][%d] = {\n%s\n};\n" % (args.id,
+ len(out), args.rh * args.rw / 2, data_out))
+
+ enemies = 0
+ entities_layer = find_name(data["layers"], "Entities")
+ if len(entities_layer):
+ map_ents = defaultdict(list)
+ ent_tileset = find_name(data["tilesets"], "Entities")
+ firstgid = ent_tileset.get("firstgid")
+ for obj in entities_layer["objects"]:
+ m = ((obj["x"] // tilewidth) // args.rw) \
+ + (((obj["y"] // tileheight) // args.rh) * (mw // args.rw))
+ x = obj["x"] % (args.rw * tilewidth)
+ y = obj["y"] % (args.rh * tileheight) - ent_tileset["tileheight"]
+ t = int(ent_tileset["tileproperties"][str(obj["gid"] - firstgid)]["id"])
+ # enemies start at id 10
+ if t > 9:
+ enemies += 1
+ map_ents[m].extend([t, x, y])
+ if "teleport" in obj.get("properties", {}):
+ tele = json.loads(obj["properties"]["teleport"])
+ tm = ((tele[0] // tilewidth) // args.rw) \
+ + (((tele[1] // tileheight) // args.rh) * (mw // args.rw))
+ map_ents[m].extend([tm, tele[0] % (tilewidth * args.rw), tele[1] % (tileheight * args.rh) - ent_tileset["tileheight"]])
+
+ for m, ents in map_ents.items():
+ data_out = ", ".join(["0x%02x" % e for e in ents]) + ", 0xff"
+ print("const unsigned char %s_e%d[%d] = { %s };" % (args.id, m, len(ents) + 1, data_out))
+
+ map_map = []
+ for i in range(len(out)):
+ if i in map_ents:
+ map_map.append("%s_e%d" % (args.id, i))
+ else:
+ map_map.append("(unsigned char *)0")
+
+ print("const unsigned char *%s_ents[%d] = { %s };\n" % (args.id,
+ len(out), ", ".join(map_map)))
+
+ print("const unsigned char %s_enemies = %s;" % (args.id, enemies))
+
+if __name__ == "__main__":
+ main()
+