MonoGame Tiled – Extract Texture2D

NEZ, an open source MonoGame framework extension, provides the functionality to import and render a tiled map. (.tmx) If MonoGame and NEZ isn’t a term for you, consider reading an introduction article first.

Recap: Following code does allow us to render a tiledmap with the NEZ’s ECS system

            var tmx = Core.Content.Load<TiledMap>("Map");
            Entity mapEntity = new Entity();            
            TiledMapComponent bgComponent = new TiledMapComponent(tmx, "collision", true);

But how do we only render one specific layer? And what if we would like to manipulate the Texture2D of that layer. E.g.: Applying a material, shader, matrix manipulation, …

Rendering only a specific layer is already supported by NEZ:


Manipulating the Texture2D however, isn’t. The Texture2D behind each and every layer equals the whole Texture2D of the tileset. Hence, we need to implement our own logic.

Option 1 – RenderTarget2D

Create a new Texture2D, limit the TiledMapComponent’s render layers and call the spriteBatch.Draw within an active RenderTarget2D. Done

Option 2 – Texture2D.GetData

A RenderTarget2D requires a spriteBatch which we maybe won’t have access to. In that case, we can make use of the Texture2D’s .GetData method.

    public static class TiledTileLayerExtensions
        public static Texture2D ExtractTexture2D(this TiledTileLayer layer)
            List<TiledTile> tiles = layer.Tiles.Where(t => t != null).ToList();

            var mostLeft = tiles.Min(c => c.X) * Constants.TILE_WIDTH;
            var mostRight = (tiles.Max(c => c.X) * Constants.TILE_WIDTH) + Constants.TILE_WIDTH;
            var mostTop = tiles.Min(c => c.Y) * Constants.TILE_HEIGHT;
            var mostBottom = tiles.Max(c => c.Y) * Constants.TILE_HEIGHT + +Constants.TILE_HEIGHT;

            var width = mostRight - mostLeft;
            var height = mostBottom - mostTop;
            var subTextureRect = new Rectangle(mostLeft, mostTop, width, height);

            Color[] subTextureColor = new Color[width * height];

            for (int currentTile = 0; currentTile < tiles.Count; currentTile++)
                TiledTile tileDetails = tiles[currentTile];

                Color[] currentTileColor = new Color[Constants.TILE_WIDTH * Constants.TILE_HEIGHT];
                tileDetails.TextureRegion.Texture2D.GetData(0, tileDetails.TextureRegion.SourceRect, currentTileColor, 0, currentTileColor.Length);

                int tX = tileDetails.X * Constants.TILE_WIDTH;
                int tY = tileDetails.Y * Constants.TILE_HEIGHT;

                for (int x = 0; x < Constants.TILE_WIDTH; x++)
                    for (int y = 0; y < Constants.TILE_HEIGHT; y++)
                        subTextureColor[(y + tY) * width + (x + tX)] = currentTileColor[y * Constants.TILE_WIDTH + x];

            Texture2D subTexture = new Texture2D(Core.GraphicsDevice, width, height);
            return subTexture;

Call the extension method with

            var textureLayer = tmx?.Layers.Where(l => l.Name == "LayerToExtract").SingleOrDefault();
            return (textureLayer as TiledTileLayer)?.ExtractTexture2D();

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.