Difference between revisions of "Using TiledNet"

From TRCCompSci - AQA Computer Science
Jump to: navigation, search
(Install TiledCS)
(Con's)
 
(17 intermediate revisions by the same user not shown)
Line 1: Line 1:
=Install TiledCS=
+
=Install TiledNet=
 
The easiest method is to create your MonoGame project then:
 
The easiest method is to create your MonoGame project then:
 
# Click on project & select Nuget Package Manager
 
# Click on project & select Nuget Package Manager
 
# Search online for TiledNet & Install
 
# Search online for TiledNet & Install
 
# In the Game1.cs of your project add: <syntaxhighlight lang=csharp>using Tiled;</syntaxhighlight>
 
# In the Game1.cs of your project add: <syntaxhighlight lang=csharp>using Tiled;</syntaxhighlight>
 +
 +
You can also get the source code from the link below, and copy the `.cs` files into the same folder as your `Game1.cs` or in a new folder within this.
 +
 +
=Pro's=
 +
* Can Load & SAVE the map
 +
 +
=Con's=
 +
* Complex draw method
 +
* doesn't cope well with multiple tilesets in one map
 +
* Archived project
 +
* No example of how to draw the map online (but now see below)
  
 
=Documentation=
 
=Documentation=
 
https://github.com/napen123/Tiled.Net
 
https://github.com/napen123/Tiled.Net
 +
 +
=Drawing A Map=
 +
 +
Here is an example of the draw code required to render the map. The map doesn't seem to split the tile values in Data into actual tiles it leaves them all in a single string.
 +
 +
<syntaxhighlight lang=c#>
 +
            foreach (var l in map.Layers)
 +
            {
 +
 +
                if (l.GetType() == typeof(TiledTileLayer))
 +
                {
 +
                    TiledTileLayer layer = l as TiledTileLayer;
 +
                    string[] tiles = layer.Data.Data.Split(",");
 +
                    tiles[0] = tiles[0].Substring(2);
 +
                    for (int i = 0; i < tiles.Length; i++) // loop to cycle through each tile
 +
                    {
 +
                        int gid = Convert.ToInt32(tiles[i]);
 +
 +
                        // Empty tile, do nothing
 +
                        if (gid == 0)
 +
                        {
 +
 +
                        }
 +
                        else
 +
                        {
 +
                            int tileFrame = gid-1;
 +
                            int column = (tileFrame % 16); // 16 is columns in the tileset
 +
                            int row = (int)Math.Floor((double)tileFrame / (double)16); // 16 is columns in the tileset
 +
 +
 +
                            float x = ((i % map.Width)) * map.TileWidth;
 +
                            float y = ((float)Math.Floor(i / (double)map.Width)) * map.TileHeight;
 +
 +
                            Rectangle tilesetRec = new Rectangle(map.TileWidth * column, map.TileHeight * row, map.TileWidth, map.TileHeight);
 +
 +
                            Game1._spriteBatch.Draw(tileset, new Rectangle((int)x, (int)y, map.TileWidth, map.TileHeight), tilesetRec, Color.White);
 +
                        }
 +
                    }
 +
 +
                }
 +
                else if (l.GetType() == typeof(TiledObjectGroup))
 +
                {
 +
                    TiledObjectGroup layer = l as TiledObjectGroup;
 +
                    foreach(TiledObject to in layer.Objects)
 +
                    {
 +
                        _spriteBatch.Draw(pixel, new Rectangle((int)to.X, (int)to.Y, (int)to.Width, (int)to.Height), Color.White);
 +
                    }
 +
                }
 +
            }
 +
</syntaxhighlight>
 +
 +
To fix this you could construct the Tiles data in the LoadContent method using something like this:
 +
 +
<syntaxhighlight lang=c#>
 +
foreach (var l in map.Layers)
 +
            {
 +
 +
                if (l.GetType() == typeof(TiledTileLayer))
 +
                {
 +
                    TiledTileLayer layer = l as TiledTileLayer;
 +
                    string[] tiles = layer.Data.Data.Split(",");
 +
                    tiles[0] = tiles[0].Substring(2);
 +
                    foreach(string i in tiles)
 +
                    {
 +
                        TiledTileData temp = new TiledTileData();
 +
                        temp.GlobalId = Convert.ToInt32(i);
 +
                        layer.Data.Tiles.Add(temp);
 +
                    }
 +
                }
 +
            }
 +
</syntaxhighlight>
 +
 +
Then the draw method could be just this:
 +
 +
<syntaxhighlight lang=c#>
 +
            foreach (var l in map.Layers)
 +
            {
 +
                if (l.GetType() == typeof(TiledTileLayer))
 +
                {
 +
                    TiledTileLayer layer = l as TiledTileLayer;
 +
 +
                    for (int i = 0; i < layer.Data.Tiles.Count; i++) // loop to cycle through each tile
 +
                    {
 +
                        int gid = Convert.ToInt32(layer.Data.Tiles[i].GlobalId);
 +
 +
                        // Empty tile, do nothing
 +
                        if (gid == 0)
 +
                        {
 +
 +
                        }
 +
                        else
 +
                        {
 +
                            int tileFrame = gid-1;
 +
                            int column = (tileFrame % 16); // 16 is columns in the tileset
 +
                            int row = (int)Math.Floor((double)tileFrame / (double)16); // 16 is columns in the tileset
 +
 +
 +
                            float x = ((i % map.Width)) * map.TileWidth;
 +
                            float y = ((float)Math.Floor(i / (double)map.Width)) * map.TileHeight;
 +
 +
                            Rectangle tilesetRec = new Rectangle(map.TileWidth * column, map.TileHeight * row, map.TileWidth, map.TileHeight);
 +
 +
                            Game1._spriteBatch.Draw(tileset, new Rectangle((int)x, (int)y, map.TileWidth, map.TileHeight), tilesetRec, Color.White);
 +
                        }
 +
                    }
 +
 +
                }
 +
                else if (l.GetType() == typeof(TiledObjectGroup))
 +
                {
 +
                    TiledObjectGroup layer = l as TiledObjectGroup;
 +
                    foreach(TiledObject to in layer.Objects)
 +
                    {
 +
                        _spriteBatch.Draw(pixel, new Rectangle((int)to.X, (int)to.Y, (int)to.Width, (int)to.Height), Color.White);
 +
                    }
 +
                }
 +
            }
 +
</syntaxhighlight>
 +
 +
=Saving TMX Map=
 +
Probably the best feature of Tiled.Net is the ability to save a TMX map. You could therefore start the game with the complete map, collect and kill enemy objects and then save the map to record your current position and the state of the game. The example below links saving the map to pressing the Escape key or Back button on a gamepad:
 +
 +
<syntaxhighlight lang=c#>
 +
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
 +
            {
 +
                map.SaveCompact("Content/test.tmx");
 +
                Exit();
 +
            }
 +
</syntaxhighlight>
 +
 +
I have tested and these saved maps can be reloaded into Tiled.Net. However I have struggled to get the Tiled Editor to open the files created, I always get "Corrupted Layer" error message with the line number corresponding to the "<nowiki></data></nowiki>" tag.

Latest revision as of 12:16, 24 May 2024

Install TiledNet

The easiest method is to create your MonoGame project then:

  1. Click on project & select Nuget Package Manager
  2. Search online for TiledNet & Install
  3. In the Game1.cs of your project add:
    using Tiled;
    

You can also get the source code from the link below, and copy the `.cs` files into the same folder as your `Game1.cs` or in a new folder within this.

Pro's

  • Can Load & SAVE the map

Con's

  • Complex draw method
  • doesn't cope well with multiple tilesets in one map
  • Archived project
  • No example of how to draw the map online (but now see below)

Documentation

https://github.com/napen123/Tiled.Net

Drawing A Map

Here is an example of the draw code required to render the map. The map doesn't seem to split the tile values in Data into actual tiles it leaves them all in a single string.

            foreach (var l in map.Layers)
            {

                if (l.GetType() == typeof(TiledTileLayer))
                {
                    TiledTileLayer layer = l as TiledTileLayer;
                    string[] tiles = layer.Data.Data.Split(",");
                    tiles[0] = tiles[0].Substring(2);
                    for (int i = 0; i < tiles.Length; i++) // loop to cycle through each tile
                    {
                        int gid = Convert.ToInt32(tiles[i]);

                        // Empty tile, do nothing
                        if (gid == 0)
                        {

                        }
                        else
                        {
                            int tileFrame = gid-1;
                            int column = (tileFrame % 16); // 16 is columns in the tileset
                            int row = (int)Math.Floor((double)tileFrame / (double)16); // 16 is columns in the tileset


                            float x = ((i % map.Width)) * map.TileWidth;
                            float y = ((float)Math.Floor(i / (double)map.Width)) * map.TileHeight;

                            Rectangle tilesetRec = new Rectangle(map.TileWidth * column, map.TileHeight * row, map.TileWidth, map.TileHeight);

                            Game1._spriteBatch.Draw(tileset, new Rectangle((int)x, (int)y, map.TileWidth, map.TileHeight), tilesetRec, Color.White);
                        }
                    }

                }
                else if (l.GetType() == typeof(TiledObjectGroup))
                {
                    TiledObjectGroup layer = l as TiledObjectGroup;
                    foreach(TiledObject to in layer.Objects)
                    {
                        _spriteBatch.Draw(pixel, new Rectangle((int)to.X, (int)to.Y, (int)to.Width, (int)to.Height), Color.White);
                    }
                }
            }

To fix this you could construct the Tiles data in the LoadContent method using something like this:

foreach (var l in map.Layers)
            {

                if (l.GetType() == typeof(TiledTileLayer))
                {
                    TiledTileLayer layer = l as TiledTileLayer;
                    string[] tiles = layer.Data.Data.Split(",");
                    tiles[0] = tiles[0].Substring(2);
                    foreach(string i in tiles)
                    {
                        TiledTileData temp = new TiledTileData();
                        temp.GlobalId = Convert.ToInt32(i);
                        layer.Data.Tiles.Add(temp); 
                    }
                }
            }

Then the draw method could be just this:

            foreach (var l in map.Layers)
            {
                if (l.GetType() == typeof(TiledTileLayer))
                {
                    TiledTileLayer layer = l as TiledTileLayer;

                    for (int i = 0; i < layer.Data.Tiles.Count; i++) // loop to cycle through each tile
                    {
                        int gid = Convert.ToInt32(layer.Data.Tiles[i].GlobalId);

                        // Empty tile, do nothing
                        if (gid == 0)
                        {

                        }
                        else
                        {
                            int tileFrame = gid-1;
                            int column = (tileFrame % 16); // 16 is columns in the tileset
                            int row = (int)Math.Floor((double)tileFrame / (double)16); // 16 is columns in the tileset


                            float x = ((i % map.Width)) * map.TileWidth;
                            float y = ((float)Math.Floor(i / (double)map.Width)) * map.TileHeight;

                            Rectangle tilesetRec = new Rectangle(map.TileWidth * column, map.TileHeight * row, map.TileWidth, map.TileHeight);

                            Game1._spriteBatch.Draw(tileset, new Rectangle((int)x, (int)y, map.TileWidth, map.TileHeight), tilesetRec, Color.White);
                        }
                    }

                }
                else if (l.GetType() == typeof(TiledObjectGroup))
                {
                    TiledObjectGroup layer = l as TiledObjectGroup;
                    foreach(TiledObject to in layer.Objects)
                    {
                        _spriteBatch.Draw(pixel, new Rectangle((int)to.X, (int)to.Y, (int)to.Width, (int)to.Height), Color.White);
                    }
                }
            }

Saving TMX Map

Probably the best feature of Tiled.Net is the ability to save a TMX map. You could therefore start the game with the complete map, collect and kill enemy objects and then save the map to record your current position and the state of the game. The example below links saving the map to pressing the Escape key or Back button on a gamepad:

            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
            {
                map.SaveCompact("Content/test.tmx");
                Exit();
            }

I have tested and these saved maps can be reloaded into Tiled.Net. However I have struggled to get the Tiled Editor to open the files created, I always get "Corrupted Layer" error message with the line number corresponding to the "</data>" tag.