Tiled tmx (CSV non-infinite) map converter tool

Hello everyone, I wanted to share a script I’m working on in Python 3:

# data exists in .\Tiled_maps\*
# need to convert all tmx map files to tilemap files for Defold w/o 
# accessing the Tiled process
import sys
import xml.parsers.expat
import codecs
import getopt

inputfile = ''
outputfile = ''
state = 0
try:
    opts, args = getopt.getopt(sys.argv,"h:i:o:",["ifile=","ofile="])
    for arg in args:
        if state == 0: # read opts
            if arg == "-i":
                state = 1
            elif arg == "-o":
                state = 2
        else:
            if state == 1: # read input file
                inputfile = arg
            elif state == 2: # read output file
                outputfile = arg
            state = 0
except getopt.GetoptError:
    print ('tiled_to_defold.py -i <inputfile> -o <outputfile>')
    sys.exit(2)

layer_name = ""
layer_width = ""
layer_height = ""
cdata = ""
odata = ""

def start_element(name, attrs):
    global layer_name, layer_width, layer_height, cdata
    if name == "layer":
        layer_name = attrs['name']
        layer_width = attrs['width']
        layer_height = attrs['height']
        cdata = ""
    return
def end_element(name):
    global odata, cdata
    if name == "layer":
        y = int(layer_height)-1
        x = 1
        odata += "layers {\n"
        odata += "  id: \"" + layer_name + "\"\n"
        if layer_name == "background":
            odata += "  z: 0\n"
        elif layer_name == "walls":
            odata += "  z: 0.01\n"
        elif layer_name == "entities":
            odata += "  z: 1\n"
        odata += "  is_visible: 1\n"
        split_data = cdata.strip().split(',')
        for d in split_data:
            if int(d) != 0:
                odata += "  cell {\n"
                odata += "    x: " + str(x-1) + "\n"
                odata += "    y: " + str(y) + "\n"
                odata += "    tile: " + str(int(d.replace("\n", ""))-1) + "\n"
                odata += "    h_flip: 0\n"
                odata += "    v_flip: 0\n"
                odata += "  }\n"
            x += 1
            if x > int(layer_width):
                x = 1
                y -= 1
        odata += "}\n"
    return
def char_data(data):
    global cdata
    cdata += data
    return
    
p = xml.parsers.expat.ParserCreate()

p.StartElementHandler = start_element
p.EndElementHandler = end_element
p.CharacterDataHandler = char_data

tmx = open(inputfile, "r")
tmx_str = tmx.read()
parsed = p.Parse(tmx_str)

with codecs.open(outputfile, "w", "utf-8") as output_map:
    output_map.write("tile_set: \"/assets/gfx/gametiles.tilesource\"\n")
    output_map.write(odata + "\n")
    output_map.write("material: \"/builtins/materials/tile_map.material\"\n")
    output_map.write("blend_mode: BLEND_MODE_ALPHA\n")
    output_map.close

To use, simply modify the script to set the Z-values you desire for the named layers and update the tile_set path to whatever tilesource you plan to use. I’m now using this in my project to speed up conversion of the map files. I’m probably going to add batch map conversion functionality soon as well if anyone is interested in that. :slight_smile:

If anyone has questions feel free to ask!

4 Likes