Frage

I'm trying to make a simple tile based game engine in C#, just for fun.

When I'm simply load an image and draw it all over the panel inside 2 for loops, it works fine. Now I'm decided to make a Map class to handle XML maps, but it's not working as I expected.

I think, the problem is in the XML reader part, but I don't know what's that.

As you can see on the below image, the default "noimage" was displaying on the panel. However, it needs to display the map using the informations from the xml files. (Load the image, cut it into tiles, then draw it to the panel inside the for loops).

The main code inside Form1:

Map testmap = new Map("test.xml");

for (int y = 0; y < testmap.Height; y += 1)
{
    for (int x = 0; x < testmap.Width; x += 1)
    {
        int t = int.Parse(testmap.Data[y].Substring(x, 1));
        e.Graphics.DrawImage(testmap.TileSet, new Rectangle(x*32, y*32, 32, 32), testmap.Tiles[t], GraphicsUnit.Pixel); 
    }
}

Map.cs:

class Map
{
    public string File = "";
    public int Width = 0;
    public int Height = 0;

    public List<string> Data = new List<string>();

    public Image TileSet = Image.FromFile("data/tiles/default.png");
    public List<Rectangle> Tiles = new List<Rectangle>();

    public Map(string fname)
    {
        File = fname;
        XmlTextReader xml = new XmlTextReader("data/maps/" + File);
        while (xml.Read())
        {
            if (xml.Name == "tileset")
            {
                XmlTextReader xml2 = new XmlTextReader("data/tiles/" + xml.Value);
                while (xml2.Read())
                {
                    if (xml2.Name == "image")
                    {
                        TileSet = Image.FromFile("data/tiles/" + xml2.Value);
                    }
                    else if (xml2.Name == "tile")
                    {
                        xml2.MoveToAttribute("x");
                        int x = int.Parse(xml2.Value);
                        xml2.MoveToAttribute("y");
                        int y = int.Parse(xml2.Value);

                        Tiles.Add(new Rectangle(x, y, 32, 32));
                    }
                }
            }
            else if (xml.Name == "w")
            {
                Width = int.Parse(xml.Value);
            }
            else if (xml.Name == "h")
            {
                Height = int.Parse(xml.Value);
            }
            else if (xml.Name == "row")
            {
                Data.Add(xml.Value);
            }
        }
    }
}

data/maps/map.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- Test Map -->
<tileset>grass.xml</tileset>
<w>16</w>
<h>16</h>
<map>
    <row>0000000000000000</row>
    <row>0001000000001000</row>
    <row>0000000110000000</row>
    <row>0000000000000000</row>
    <row>0001000000001000</row>
    <row>0000000110000000</row>
    <row>0000000000000000</row>
    <row>0001000000001000</row>
    <row>0000000110000000</row>
    <row>0000000000000000</row>
    <row>0001000000001000</row>
    <row>0000000110000000</row>
    <row>0000000000000000</row>
    <row>0001000000001000</row>
    <row>0000000110000000</row>
    <row>0000000000000000</row>
</map>

data/tiles/grass.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- Grass TileSet -->
<image>grass.png</image>
<tileset>
    <tile x="16" y="48"></tile>
    <tile x="0" y="0"></tile>
</tileset>

The problem

War es hilfreich?

Lösung

Iv basically changed the whole system around. iv managed to draw the map to a windows form.

Here is how your Map class should look:

[XmlTypeAttribute(AnonymousType = true)]
[XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class Map
{
    private string[] tilesetField;
    private byte widthField;
    private byte heightField;
    private string[] dataField;

    [XmlArrayItemAttribute("tile", IsNullable = false)]
    public string[] tileset
    {
        get
        {
            return tilesetField;
        }
        set
        {
            tilesetField = value;
        }
    }

    public byte width
    {
        get
        {
            return widthField;
        }
        set
        {
            widthField = value;
        }
    }

    public byte height
    {
        get
        {
            return heightField;
        }
        set
        {
            heightField = value;
        }
    }

    [XmlArrayItemAttribute("row", IsNullable = false)]
    public string[] data
    {
        get
        {
            return dataField;
        }
        set
        {
            dataField = value;
        }
    }
}

This is how your XML should look:

<?xml version="1.0" encoding="UTF-8"?>
<Map>
  <tileset>
    <tile>grass.png</tile>
    <tile>grass1.png</tile>
  </tileset>
  <width>16</width>
  <height>16</height>
  <data>
    <row>0000000000000000</row>
    <row>0001000000001000</row>
    <row>0000000110000000</row>
    <row>0000000000000000</row>
    <row>0001000000001000</row>
    <row>0000000110000000</row>
    <row>0000000000000000</row>
    <row>0001000000001000</row>
    <row>0000000110000000</row>
    <row>0000000000000000</row>
    <row>0001000000001000</row>
    <row>0000000110000000</row>
    <row>0000000000000000</row>
    <row>0001000000001000</row>
    <row>0000000110000000</row>
    <row>0000000000000000</row>
  </data>
</Map>

Now you can simply draw the map like this:

private void panel1_Paint(object sender, PaintEventArgs e)
{
    XmlSerializer ser = new XmlSerializer(typeof(Map));
    Map testmap;
    using (XmlReader reader = XmlReader.Create("test.xml"))
    {
        testmap = (Map)ser.Deserialize(reader);
    }

    for (int y = 0; y < testmap.height; y += 1)
    {
        for (int x = 0; x < testmap.width; x += 1)
        {
            int t = int.Parse(testmap.data[y].Substring(x, 1));
            e.Graphics.DrawImage(Image.FromFile(testmap.tileset[t]), new Rectangle(x * 32, y * 32, 32, 32));
        }
    }
}

So basically the XML can explain exactly how it works,
Firstly, like your first design the map had a width and height. The map also has tiles, these tiles are listed in the tileset. The order they are in is the index of the tile. Then the data of the map is rows and columns of tile indexes.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top