在关卡选择屏幕、XML、XNA 上保存和加载数据
Posted
技术标签:
【中文标题】在关卡选择屏幕、XML、XNA 上保存和加载数据【英文标题】:Saving & loading data on level selection screen, XML, XNA 【发布时间】:2014-06-24 16:34:23 【问题描述】:我正在制作一个基本的平台游戏,这是我的第一款游戏。我遇到了一些问题。到目前为止,游戏只有一个关卡,它是从 .txt 文件加载的。不过我想要一个 Angry Birdish 的世界/关卡选择屏幕。
计划是为每个级别显示一个图标,但仅到目前为止已完成的级别和下一个可访问。此外,对于已完成的关卡,分数(星星等)将显示在图标下方。
我不想从 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。但是,在保存时,我是否需要加载以前的状态(旧列表),然后处理涉及某些索引的列表,然后删除 te 文件,并再次保存。
这可能会为系统故障打开一个简单的方法,例如,如果保存出现问题或电源故障。整个文件将丢失或损坏。我想这可以通过使用备份文件然后检查主文件的完整性来解决,但现在对于像我这样的初学者来说,它开始感觉像是一座需要爬的山。
在 GameDev 上尝试过这个问题后,我将在这里澄清主要问题:
1) 我可以在包含所有级别信息的 XML 文件中只保存一个或两个级别的信息吗? IE。我可以使用一些索引来将写入操作指向一个特定的部分,然后该部分将被覆盖/替换。
2)如果没有,有什么方法可以安全地从文件中加载所有信息,删除文件,在需要的地方修改后保存所有信息。
在研究了这个 Json 的东西之后,我成功地序列化了测试级别的信息。但是,反序列化失败,因为我有一个矩形作为对象的一部分。错误如下:
将值“X:1 Y:1 Width:1 Height:1”转换为类型“Microsoft.Xna.Framework.Rectangle”时出错。路径“[0].Rectangle”,第 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 文件中。我确实需要绘图的矩形信息。
【问题讨论】:
【参考方案1】:因此,承诺的答案来了。
我个人更喜欢使用 JSon 来存储数据,因为它比 XML 更容易使用,并且占用的存储空间更少。您要做的是为您的玩家、敌人、物品、场景对象等创建数据模型。
然后,您需要 JsonConvert.SerializeObject() 一个父数据模型,它将包含所有这些内容。
将此保存在任何文件中,并在加载时再次反序列化,并从头开始重建所有对象。
或者,只需将您正在使用的类中的所有属性公开即可。这样,JsonConvert 将能够实际序列化整个模型。请记住,如果您执行此运行时,它将更多地生成关卡当前状态的完整快照。阿卡。敌人所在的位置、剩余的生命值以及您可能拥有的任何其他值。
我希望这能回答你的问题。
【讨论】:
Json 似乎是一个有趣的选择,尤其是由于文件较小。但是,似乎我需要添加一些库/引用才能真正获得对 Json 的访问权限。有一个例子是添加 using 语句来获得 Json 功能,但似乎情况发生了变化,这样的语句不再起作用。 问题是,选择哪一个:james.newtonking.com/json 或 codeproject.com/Articles/159450/fastJSON 我的目标是最终拥有可以在 WP、android 和 ios 上运行的东西,那么这个 Json 业务是否会造成潜在的危害?至少 Newtonsoft Json 声称兼容性很高,所以我认为可能涉及一些问题。 据我所知,Json 可以在任何存在的平台上运行(嗯,你知道,任何著名的平台)。是的,要么使用james.newtonking.com/json 要么去VS包管理器并写“安装包Newtonsoft.Json”以上是关于在关卡选择屏幕、XML、XNA 上保存和加载数据的主要内容,如果未能解决你的问题,请参考以下文章