Skip to content

Instantly share code, notes, and snippets.

@mattj1
Last active August 23, 2025 16:20
Show Gist options
  • Select an option

  • Save mattj1/367612d16bb8ede88a0e75ae6ea25f06 to your computer and use it in GitHub Desktop.

Select an option

Save mattj1/367612d16bb8ede88a0e75ae6ea25f06 to your computer and use it in GitHub Desktop.

Revisions

  1. mattj1 revised this gist Sep 28, 2020. 1 changed file with 9 additions and 4 deletions.
    13 changes: 9 additions & 4 deletions TMXLoader.cs
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,6 @@
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Reflection;
    using System.Xml;
    using System.Xml.Serialization;
    @@ -14,7 +15,7 @@ public class TMXLoader
    private readonly string _fileName;

    public delegate Texture2D TextureLoader(string source);
    public delegate XmlReader XmlLoader(string source);
    public delegate Stream XmlLoader(string source);

    private TextureLoader _textureLoader;
    private XmlLoader _xmlLoader;
    @@ -192,9 +193,9 @@ private TiledMapTileset ConvertTiledMapTileset(TiledMapTilesetContent tsc)
    private TiledMap ConvertTiledMap()
    {
    var xmlSerializer = new XmlSerializer(typeof(TiledMapContent));
    var xmlReader = _xmlLoader(_fileName);
    var stream = _xmlLoader(_fileName);

    TiledMapContent tiledMapContent = (TiledMapContent) xmlSerializer.Deserialize(xmlReader);
    TiledMapContent tiledMapContent = (TiledMapContent) xmlSerializer.Deserialize(XmlReader.Create(stream));

    TiledMap tiledMap = new TiledMap(tiledMapContent.Name, tiledMapContent.Width, tiledMapContent.Height,
    tiledMapContent.TileWidth, tiledMapContent.TileHeight,
    @@ -212,10 +213,13 @@ private TiledMap ConvertTiledMap()

    if (tileSetContent.Source != null)
    {
    Stream stream1 = _xmlLoader(tileSetContent.Source);
    // load content from file
    content =
    (TiledMapTilesetContent) new XmlSerializer(typeof(TiledMapTilesetContent)).Deserialize(
    _xmlLoader(tileSetContent.Source));
    XmlReader.Create(stream1));

    stream1.Close();
    }

    TiledMapTileset tileSet = ConvertTiledMapTileset(content);
    @@ -239,6 +243,7 @@ private TiledMap ConvertTiledMap()
    }
    }

    stream.Close();
    return tiledMap;
    }

  2. mattj1 created this gist Sep 28, 2020.
    251 changes: 251 additions & 0 deletions TMXLoader.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,251 @@
    using System;
    using System.Collections.Generic;
    using System.Reflection;
    using System.Xml;
    using System.Xml.Serialization;
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Graphics;
    using MonoGame.Extended.Tiled.Serialization;

    namespace MonoGame.Extended.Tiled
    {
    public class TMXLoader
    {
    private readonly string _fileName;

    public delegate Texture2D TextureLoader(string source);
    public delegate XmlReader XmlLoader(string source);

    private TextureLoader _textureLoader;
    private XmlLoader _xmlLoader;

    private TMXLoader(string path, TextureLoader textureLoader, XmlLoader xmlLoader)
    {
    _fileName = path;

    _textureLoader = textureLoader;
    _xmlLoader = xmlLoader;

    Console.WriteLine($"TMX Loader: {path}");
    }

    private TiledMapObjectLayer ConvertTiledMapObjectLayer(TiledMap tiledMap
    , TiledMapObjectLayerContent lc)
    {
    List<TiledMapObject> objects = new List<TiledMapObject>();

    for (int i = 0; i < lc.Objects.Count; i++)
    {
    TiledMapObjectContent c = lc.Objects[i];

    if (c.Ellipse != null)
    {
    // Not supported
    }
    else if (c.Polygon != null)
    {
    // TODO
    // List<Point2> points = new List<Point2>();
    // var ob = new TiledMapPolygonObject(c.Identifier, c.Name, null, new Size2(c.Width, c.Height), new Vector2(c.X, c.Y), c.Rotation, 1.0f, c.Visible, c.Type );
    // objects.Add(ob);
    }
    else if (c.Polyline != null)
    {
    // TODO
    }
    else
    {
    TiledMapTileset tileSet = tiledMap.GetTilesetByTileGlobalIdentifier((int) c.GlobalIdentifier);
    if (tileSet != null)
    {
    var fgi = tiledMap.GetTilesetFirstGlobalIdentifier(tileSet);
    int localIdentifier = (int) (c.GlobalIdentifier - fgi);
    TiledMapTilesetTile tile = null;

    foreach (var t in tileSet.Tiles)
    {
    if (t.LocalTileIdentifier == localIdentifier)
    {
    tile = t;
    break;
    }
    }

    // Copy properties

    var tmo = new TiledMapTileObject(c.Identifier, c.Name, tileSet, tile,
    new Vector2(c.Width, c.Height), new Vector2(c.X, c.Y), c.Rotation
    , 1.0f, c.Visible, c.Type);

    foreach (var prop in c.Properties)
    {
    tmo.Properties.Add(prop.Name, prop.Value);
    }

    objects.Add(tmo);
    }
    else
    {
    Console.WriteLine($"Warning: no tileset for object gid {c.GlobalIdentifier}");
    }
    }
    }

    TiledMapObjectLayer layer = new TiledMapObjectLayer(lc.Name, objects.ToArray(),
    ColorHelper.FromHex(lc.Color),
    (TiledMapObjectDrawOrder) lc.DrawOrder,
    new Vector2(lc.OffsetX, lc.OffsetY), lc.Opacity, lc.Visible);

    return layer;
    }

    private TiledMapTileLayer ConvertTiledMapTileLayer(TiledMap tiledMap, TiledMapTileLayerContent lc)
    {
    TiledMapTileLayer layer = new TiledMapTileLayer(lc.Name, lc.Width, lc.Height, tiledMap.TileWidth,
    tiledMap.TileHeight, null, lc.Opacity, lc.Visible);

    // Copy properties

    foreach (var prop in lc.Properties)
    {
    layer.Properties.Add(prop.Name, prop.Value);
    }

    // Copy tiles

    if (lc.Data.Encoding == "csv")
    {
    string[] tileIds = lc.Data.Value.Split(",");

    int offs = 0;
    for (ushort y = 0; y < layer.Height; y++)
    {
    for (ushort x = 0; x < layer.Width; x++)
    {
    layer.Tiles[offs] = new TiledMapTile(uint.Parse(tileIds[offs]), x, y);
    offs++;
    }
    }
    }

    return layer;
    }

    private TiledMapTileset ConvertTiledMapTileset(TiledMapTilesetContent tsc)
    {
    var texture = _textureLoader(tsc.Image.Source);

    var ts = new TiledMapTileset(texture, tsc.TileWidth, tsc.TileHeight, tsc.TileCount, tsc.Spacing, tsc.Margin,
    tsc.Columns);
    foreach (var t in tsc.Tiles)
    {
    // TODO: Objects?

    TiledMapTilesetTile tile;

    if (t.Frames.Count == 0)
    {
    tile = new TiledMapTilesetTile(t.LocalIdentifier, t.Type, null);
    }
    else
    {
    // Animation frames

    TiledMapTilesetTileAnimationFrame[] frames = new TiledMapTilesetTileAnimationFrame[t.Frames.Count];

    for (int i = 0; i < t.Frames.Count; i++)
    {
    var frameContent = t.Frames[i];

    BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance;
    object[] parameters = {ts, frameContent.TileIdentifier, frameContent.Duration};

    object instantiatedType =
    Activator.CreateInstance(typeof(TiledMapTilesetTileAnimationFrame),
    bindingFlags,
    null, parameters, null);

    frames[i] = (TiledMapTilesetTileAnimationFrame) instantiatedType;
    }

    tile = new TiledMapTilesetAnimatedTile(t.LocalIdentifier, frames, t.Type, null);
    }

    // Copy properties

    foreach (var prop in t.Properties)
    {
    tile.Properties[prop.Name] = prop.Value;
    }

    ts.Tiles.Add(tile);
    }

    foreach (var prop in tsc.Properties)
    {
    ts.Properties[prop.Name] = prop.Value;
    }

    return ts;
    }

    private TiledMap ConvertTiledMap()
    {
    var xmlSerializer = new XmlSerializer(typeof(TiledMapContent));
    var xmlReader = _xmlLoader(_fileName);

    TiledMapContent tiledMapContent = (TiledMapContent) xmlSerializer.Deserialize(xmlReader);

    TiledMap tiledMap = new TiledMap(tiledMapContent.Name, tiledMapContent.Width, tiledMapContent.Height,
    tiledMapContent.TileWidth, tiledMapContent.TileHeight,
    (TiledMapTileDrawOrder) tiledMapContent.RenderOrder,
    TiledMapOrientation.Orthogonal, ColorHelper.FromHex(tiledMapContent.BackgroundColor));

    foreach (var prop in tiledMapContent.Properties)
    {
    tiledMap.Properties[prop.Name] = prop.Value;
    }

    foreach (var tileSetContent in tiledMapContent.Tilesets)
    {
    TiledMapTilesetContent content = tileSetContent;

    if (tileSetContent.Source != null)
    {
    // load content from file
    content =
    (TiledMapTilesetContent) new XmlSerializer(typeof(TiledMapTilesetContent)).Deserialize(
    _xmlLoader(tileSetContent.Source));
    }

    TiledMapTileset tileSet = ConvertTiledMapTileset(content);
    tiledMap.AddTileset(tileSet, tileSetContent.FirstGlobalIdentifier);
    }

    foreach (var layerContent in tiledMapContent.Layers)
    {
    switch (layerContent.Type)
    {
    case TiledMapLayerType.TileLayer:
    TiledMapTileLayer layer =
    ConvertTiledMapTileLayer(tiledMap, (TiledMapTileLayerContent) layerContent);
    tiledMap.AddLayer(layer);
    break;
    case TiledMapLayerType.ObjectLayer:
    var objectLayer =
    ConvertTiledMapObjectLayer(tiledMap, (TiledMapObjectLayerContent) layerContent);
    tiledMap.AddLayer(objectLayer);
    break;
    }
    }

    return tiledMap;
    }

    public static TiledMap LoadTiledMap(string path, TextureLoader textureLoader, XmlLoader xmlLoader)
    {
    var loader = new TMXLoader(path, textureLoader, xmlLoader);
    return loader.ConvertTiledMap();
    }
    }
    }