嘿,我一直在寻找一段时间,我仍然无法找到这个问题的直接答案。我有一个XNA游戏,其中部分UI显示一个图标,每隔一段时间就会发生变化(多久不相关)。我决定使用一个简单的spritesheet制作器输出spritesheet以及一个简单的XML文件,其中包含每个单独图标的位置。
我希望能够将XML文件中相应图标的spritesheet位置和图标大小读入Rectangle
。然后我可以使用它作为绘图位的源矩形。
然而,我还没有看到如何将XML文件加载到XNA 4.0项目而不编写我自己的内容管道(我希望尽可能避免的东西)并且一旦加载如何有效(一般情况下)的简单解释)将数据提取到Rectangle
变量。
XML文件如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created with TexturePacker http://texturepacker.com-->
<!-- $TexturePacker:SmartUpdate:748fc56befb00c22540f953093f731a7$ -->
<!--Format:
n => name of the sprite
x => sprite x pos in texture
y => sprite y pos in texture
w => sprite width (may be trimmed)
h => sprite height (may be trimmed)
oX => sprite's x-corner offset (only available if trimmed)
oY => sprite's y-corner offset (only available if trimmed)
oW => sprite's original width (only available if trimmed)
oH => sprite's original height (only available if trimmed)
r => 'y' only set if sprite is rotated
-->
<TextureAtlas imagePath="Loadout_Icons.png" width="185" height="86">
<sprite n="Charge_Down.png" x="0" y="0" w="37" h="43"/>
<sprite n="Charge_Up.png" x="37" y="0" w="37" h="43"/>
<sprite n="Damage_Down.png" x="74" y="0" w="37" h="43"/>
<sprite n="Damage_Up.png" x="111" y="0" w="37" h="43"/>
<sprite n="FireRate_Down.png" x="148" y="0" w="37" h="43"/>
<sprite n="FireRate_Up.png" x="0" y="43" w="37" h="43"/>
<sprite n="Health_Down.png" x="37" y="43" w="37" h="43"/>
<sprite n="Health_Up.png" x="74" y="43" w="37" h="43"/>
<sprite n="Speed_Down.png" x="111" y="43" w="37" h="43"/>
<sprite n="Speed_Up.png" x="148" y="43" w="37" h="43"/>
</TextureAtlas>
此外,我不确定如果我不通过自己的XML文件拍摄自己,那会更容易吗?
我已经阅读了msdn所提供的大部分内容但无济于事,但我们非常感谢任何相关页面或问题的链接。 提前致谢。
答案 0 :(得分:0)
以下应该有效,但是,它完全未经测试:
[XmlRoot("TextureAtlas", IsNullable = false)]
public class TextureAtlasXml
{
public static TextureAtlasXml FromFile(String file)
{
using (var stream = File.OpenRead(file))
{
return FromStream(stream);
}
}
public static TextureAtlasXml FromStream(Stream stream)
{
var serializer = new XmlSerializer(typeof(TextureAtlasXml));
return (TextureAtlasXml)serializer.Deserialize(stream);
}
[XmlAttribute("imagePath")]
public String ImagePath;
[XmlAttribute("width")]
public Int32 Width;
[XmlAttribute("height")]
public Int32 Height;
[XmlElement("sprite")]
public List<SpriteXml> Sprites;
}
public class SpriteXml
{
[XmlAttribute("n")]
public String Name;
[XmlAttribute("x")]
public Int32 X;
[XmlAttribute("y")]
public Int32 Y;
[XmlAttribute("w")]
public Int32 Width;
[XmlAttribute("h")]
public Int32 Height;
public Rectangle Rectangle { get { return new Rectangle(this.X, this.Y, this.Width, this.Height); } }
}
我建议您考虑使用内容管道,因为它提供了一个很好的解决方案,但是,代码应该像您想要的那样工作。
答案 1 :(得分:0)
如果您愿意使用Sprite Vortex(实际上是特定版本),您可以使用以下类。 您必须使用Sprite Vortex 1.2.2,因为在较新版本中,XML格式已更改。确保添加属性的XML文件已更改为“不编译”。
如果您需要一个工作示例,我可以发给您一个非常简单的例子。
P.S。 Sprite Vortex应该使用其他程序执行相同的操作,但是v 1.2.2非常错误但不是太糟糕。
答案 2 :(得分:0)
正如我在评论中提到的那样,我决定说我最终使用了NikoDrašković关于专门为纹理封隔器制作的专用管道扩展的建议,可以在http://thirdpartyninjas.com/blog/2012/08/02/texturepacker-xna-content-pipeline-extension/找到。这使得处理纹理打包器生成的XML文件变得非常容易。
然而,作为一个侧面说明和我重新审视这个问题的另一个原因是我最近在使用XML做了很多工作(试图更好地理解它们)以及最好的方法我发现处理读取自定义XML文件而不为每个文件编写新的管道扩展(如现在看起来那样优雅)如下所示。我将XML文件添加到内容目录中,就像添加任何其他纹理一样。在XML的属性中,我将构建操作设置为“内容”,然后复制到输出目录到“始终复制”。从这里我有一个单独的类,我在其中传入文件的名称,并在其中处理我需要的所有XML。这些课程以:
开头Stream stream = TitleContainer.OpenStream("Content\\" + fileName + ".xml");
XDocument doc = XDocument.Load(stream);
然后继续(使用System.Xml.Linq库的其余部分)来读取和存储适当的数据,并使用方法轻松访问数据。这可能不是解决问题的最佳方法,但它已经为我工作,并且很容易理解和快速实施。希望这可以帮助其他任何有类似问题的人。