储蓄,在关卡选择屏幕上加载数据,XML, XNA
本文关键字:加载 数据 XNA XML 选择 储蓄 屏幕 | 更新日期: 2023-09-27 18:10:10
我正在制作一款基础平台游戏,这是我的第一款游戏。我遇到了点小麻烦。到目前为止,这款游戏只有一个关卡,并且是从。txt文件中加载的。但是我想要一个类似《愤怒的小鸟》的世界/关卡选择界面。
我们的计划是让每个关卡都有一个可见的图标,但只有到目前为止完成的关卡和下一个可以访问。此外,对于已完成的关卡,分数(星星等)将显示在图标下。
我不希望从XML加载关卡,至少现在还没有。只有需要读写的持久世界数据。我认为最简单的方法是从XML中加载关卡选择屏幕的格式,而不是使用我目前使用的方法(文本文件)。
我想我可以对文本文件这样做,但是我真的不喜欢编写和排序文件的想法。然后我发现xml文件在这方面的问题应该少一些。然而,由于我以前从来没有处理过xml文件,因此产生了额外的问题。
有没有人能给我指出一个关于这类事情的教程的方向,或者一些你可能遇到的完成至少相对类似结果的示例。我不期望任何人为我做编码,但如果你有指针或时间和耐心提供一个样本,我将非常感激。
在进一步挖掘和摸索旧XNA版本的教程之后,我设法产生了以下保存/加载类:
namespace SaveLoadXML
{
class SaveLoad
{
public LevelInfo Load (int id)
{
LevelInfo level;
// Get the path of the save game
string fullpath = "World.xml";
// Open the file
FileStream stream = File.Open(fullpath, FileMode.OpenOrCreate,
FileAccess.Read);
try
{
// Read the data from the file
XmlSerializer serializer = new XmlSerializer(typeof(LevelInfo));
level = (LevelInfo)serializer.Deserialize(stream);
}
finally
{
// Close the file
stream.Close();
}
return (level);
}
public void Save (LevelInfo level, int id)
{
// Get the path of the save game
string fullpath = "World.xml";
// Open the file, creating it if necessary
FileStream stream = File.Open(fullpath, FileMode.OpenOrCreate);
try
{
// Convert the object to XML data and put it in the stream
XmlSerializer serializer = new XmlSerializer(typeof(LevelInfo));
serializer.Serialize(stream, level);
}
finally
{
// Close the file
stream.Close();
}
}
}
}
现在我开始思考,是否有一种方法可以针对xml文件的特定部分,或者总是从头开始编写?我看到的几乎所有示例在开始时都有一个条件:如果文件存在,则删除它,然后写入。
我假设我可以(甚至应该?)制作一个LevelInfo对象列表,并一次加载它们,因为无论如何都不需要加载单个LevelInfo。然而,在保存时,我是否需要加载以前的状态(旧列表),然后根据所涉及的某些索引操作列表,然后删除文件,并再次保存它。
如果在保存或电源故障中出现错误,这可能会为系统打开一个容易失败的方法。整个文件将丢失或损坏。我想这可以通过使用备份文件,然后检查主文件的完整性来解决,但是现在对于像我这样的初学者来说,这开始感觉像爬了一座山。
在GameDev上尝试过这个问题后,我将在这里澄清主要问题:
1)我能否在包含所有关卡信息的xml文件中只保存一个或两个关卡的信息?ie。我是否可以使用一些索引将写操作指向一个特定的部分,然后该部分将被覆盖/替换。
2)如果没有,是否有任何方法可以安全地从文件中加载所有信息,删除文件,在需要修改后保存所有信息
经过一些研究这个Json的东西,我已经成功地序列化测试级别的信息。然而,反序列化失败,因为我有一个矩形作为对象的一部分。错误如下:
将值"{X:1 Y:1宽:1高:1}"转换为类型" Microsoft.Xna.Framework.Rectangle "时出错。路[0]。矩形',第6行,位置46.
class LevelInfo
{
public int ID { get; set; }
public Vector2 Dimensions { get; set; }
public Vector2 Position { get; set; }
public Rectangle Rectangle { get; set; }
public int Stars { get; set; }
public string Text { get; set; }
}
class SaveLoadJSON
{
public static List<LevelInfo> Load()
{
List<LevelInfo> levels = new List<LevelInfo>();
using (StreamReader file = File.OpenText("World.json"))
{
JsonSerializer serializer = new JsonSerializer();
levels = (List<LevelInfo>)serializer.Deserialize(file, typeof(List<LevelInfo>));
}
return levels;
}
public static void Save(List<LevelInfo> levels)
{
if (File.Exists("World.json"))
{
File.Delete("World.json");
}
using (FileStream fs = File.Open("World.json", FileMode.CreateNew))
using (StreamWriter sw = new StreamWriter(fs))
using (JsonWriter jw = new JsonTextWriter(sw))
{
jw.Formatting = Formatting.Indented;
JsonSerializer serializer = new JsonSerializer();
serializer.Serialize(jw, levels);
}
}
}
有办法解决这个问题吗?对于像我这样的初学者来说,最好是一个相对简单的方法。
或者,是否有一种方法可以省略开始的矩形信息,然后可能添加它?如果我没有向矩形输入任何内容,它仍然会以0值添加到json文件中。我确实需要矩形信息来绘制。
承诺的答案来了。
我个人更喜欢使用JSon来存储数据,因为它比XML更容易使用,占用的存储空间更少。你要做的是为玩家、敌人、道具、场景对象等创建数据模型。
然后,您将需要JsonConvert.SerializeObject()一个父数据模型,它将包含所有这些东西。
将其保存在任何文件中,并在加载时再次反序列化,并从头开始重建所有对象。
或者,在你已经使用的类中拥有所有属性,是公共的。这样,JsonConvert将能够序列化整个模型。请记住,如果您执行此运行时,它将生成更多的关卡当前状态的完整快照。又名。敌人的位置,剩余的生命值以及你可能拥有的任何东西。
我希望这能回答你的问题