From 819c7899b3452a405bac6300fe44460ca9e5dcd6 Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Sun, 7 Sep 2025 10:55:19 -0700 Subject: Add support for multiple layers. --- tools/mkasset.py | 56 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 23 deletions(-) (limited to 'tools') diff --git a/tools/mkasset.py b/tools/mkasset.py index a402e3c..1be0573 100644 --- a/tools/mkasset.py +++ b/tools/mkasset.py @@ -12,6 +12,7 @@ # import argparse import ctypes +import struct import sys from enum import IntEnum from typing import Generator @@ -80,7 +81,8 @@ def convert_tsx(input_filepath, output_filepath): assert (tileset.tag == "tileset") # Header. - tileset_tile_count = int(tileset.attrib["tilecount"]) + # +1 for the 0-tile. + tileset_tile_count = int(tileset.attrib["tilecount"]) + 1 tileset_tile_width = int(tileset.attrib["tilewidth"]) tileset_tile_height = int(tileset.attrib["tileheight"]) @@ -88,17 +90,14 @@ def convert_tsx(input_filepath, output_filepath): print(f"Tile width: {tileset_tile_width}") print(f"Tile height: {tileset_tile_height}") - pixels = [] # List of byte arrays - pixels_offset = 0 + pixels = bytearray() def output_tile(output, tile_width, tile_height, tile_image_bytes): # Expecting RGBA pixels. assert (len(tile_image_bytes) == (tile_width * tile_height * 4)) - nonlocal pixels_offset - tile_pixels_offset = pixels_offset - pixels.append(tile_image_bytes) - pixels_offset += len(tile_image_bytes) + tile_pixels_offset = len(pixels) + pixels.extend(tile_image_bytes) output.write(ctypes.c_uint16(tile_width)) output.write(ctypes.c_uint16(tile_height)) @@ -111,6 +110,10 @@ def convert_tsx(input_filepath, output_filepath): output.write(ctypes.c_uint16(tileset_tile_height)) output.write(ctypes.c_uint16(0)) # Pad. + # Write the 0-tile, which denotes "no tile", at index 0. + zero_pixels = bytes(tileset_tile_width * tileset_tile_height * 4) + output_tile(output, tileset_tile_width, tileset_tile_height, zero_pixels) + # A tileset made up of multiple images contains various 'tile' children, # each with their own 'image': # @@ -174,8 +177,7 @@ def convert_tsx(input_filepath, output_filepath): output_tile(output, tile_width, tile_height, image_bytes) # Write the pixel data. - for bytes in pixels: - output.write(bytes) + output.write(pixels) def convert_tmx(input_filepath, output_filepath): @@ -187,8 +189,10 @@ def convert_tmx(input_filepath, output_filepath): map_height = int(root.attrib["height"]) base_tile_width = int(root.attrib["tilewidth"]) base_tile_height = int(root.attrib["tileheight"]) - num_layers = 1 flags = Orientation.Isometric if (root.attrib["orientation"] == "isometric") else Orientation.Orthogonal + firstgid = 1 + layers = [] + tileset_path = "" print(f"Map width: {map_width}") print(f"Map height: {map_height}") @@ -196,8 +200,6 @@ def convert_tmx(input_filepath, output_filepath): print(f"Tile height: {base_tile_height}") print(f"Orientation: {flags}") - tileset_path = None - with open(output_filepath, 'bw') as output: for child in root: if child.tag == "tileset": @@ -205,19 +207,12 @@ def convert_tmx(input_filepath, output_filepath): tileset = child tileset_path = tileset.attrib["source"] + firstgid = int(tileset.attrib["firstgid"]) print(f"Tile set: {tileset_path}") tileset_path = tileset_path.replace("tsx", "ts") - # Write the header. - output.write(to_char_array(tileset_path, MAX_PATH_LENGTH)) - output.write(ctypes.c_uint16(map_width)) - output.write(ctypes.c_uint16(map_height)) - output.write(ctypes.c_uint16(base_tile_width)) - output.write(ctypes.c_uint16(base_tile_height)) - output.write(ctypes.c_uint16(num_layers)) - output.write(ctypes.c_uint16(flags)) elif child.tag == "layer": layer = child layer_id = int(layer.attrib["id"]) @@ -238,12 +233,27 @@ def convert_tmx(input_filepath, output_filepath): csv = data.text.strip() rows = csv.split('\n') + tiles = bytearray() for row in rows: tile_ids = [x.strip() for x in row.split(',') if x] for tile_id in tile_ids: - # TODO: We need to handle 'firsgid' in TMX files. - # For now, assume it's 1 and do -1 to make the tiles 0-based. - output.write(ctypes.c_uint16(int(tile_id) - 1)) + # Subtract firstgid and then add 1 to make tiles 1-based. + tile_id = int(tile_id) - firstgid + 1 + tiles.extend(struct.pack("=h", tile_id)) + layers.append(tiles) + + # Write the header. + output.write(to_char_array(tileset_path, MAX_PATH_LENGTH)) + output.write(ctypes.c_uint16(map_width)) + output.write(ctypes.c_uint16(map_height)) + output.write(ctypes.c_uint16(base_tile_width)) + output.write(ctypes.c_uint16(base_tile_height)) + output.write(ctypes.c_uint16(len(layers))) + output.write(ctypes.c_uint16(flags)) + + # Write the layers. + for layer in layers: + output.write(layer) def get_num_cols(image, sprite_width): -- cgit v1.2.3