简体   繁体   English

如何保存和加载带有抽象对象的关卡文件?

[英]How can I save and load a level file with abstract objects?

I'm trying to make a level editor that provides a save functionality like mario maker - the user can create a level and save the level data. 我正在尝试制作一个级别编辑器,以提供诸如mario maker之类的保存功能-用户可以创建一个级别并保存级别数据。 How is this usually done? 通常如何做? Specifically what I'm struggling with is my level contains a list of Enemies (an abstract class). 具体来说,我正在努力的是自己的等级,其中包含一个敌人列表(一个抽象类)。 When I write to a file I can write the json representation of the concrete enemy classes, but when I read from the file, I'd need to know what concrete class it is in order to reconstruct it into that specific class. 当我写文件时,我可以写出具体敌人类别的json表示形式,但是当我从文件中读取时,我需要知道它是什么具体类别,以便将其重构为该特定类别。 That seems like a pain - I'd have to manually add some code to write out what class type the enemy is when it gets saved and also add code to read what class type and create an instance of that class when read. 这似乎很痛苦-我必须手动添加一些代码来写出敌人被保存时的类类型,还必须添加代码以读取类类型并在读取时创建该类的实例。 I'm afraid of maintaining that for every new Enemy that I create. 我害怕为我创建的每个新敌人都保持这种状态。 So my main question is how can I most easily read a list of concrete Enemies into a list of abstract Enemies? 所以我的主要问题是,如何最轻松地将具体敌人列表读入抽象敌人列表中? It seems like some knowledge about the class is required on save/load. 似乎在保存/加载时需要有关该类的一些知识。

Also, is saving as JSON the way to go here or is serialization better? 另外,将其另存为JSON还是序列化更好? Does it matter? 有关系吗?

Since your going to be creating concrete classes when the program starts up, you will need to know the actual class of each one. 由于您将在程序启动时创建具体的类,因此您将需要知道每个类的实际类。 There are a bunch of ways you could do this. 您可以通过多种方法来执行此操作。 To do something easy, you could add a getLabel() method to each concrete class and use that as a switch to figure out the correct concrete class. 为了简单getLabel() ,您可以向每个具体类添加一个getLabel()方法,并将其用作找出正确具体类的开关。

// Using jackson-databind
ObjectMapper mapper = new ObjectMapper();
JsonNode node = mapper.readValue(json, JsonNode.class);

Enemy enemy = null;
if (GOOMBA_LABEL.equals(node.get("label").asText()))
   enemy = mapper.readValue(json, Goomba.class);

I really like using JSON libraries functionality to parse my JSON into a POJO. 我真的很喜欢使用JSON库功能将JSON解析为POJO。 However, doing the above would actually require double parsing - 1) Parse into some generic structure (like a Map or JsonNode), check the label and then 2) Parse into POJO. 但是,执行上述操作实际上需要双重解析-1)解析为某种通用结构(例如Map或JsonNode),检查标签,然后2)解析为POJO。

Another thing you could do is prepend a "Magic Number" before each JSON string to let you know which type it is. 您可以做的另一件事是,在每个JSON字符串之前加一个“幻数”,以让您知道它是哪种类型。 Then you don't have to double parse JSON. 然后,您不必双重解析JSON。

DataInput input = new DataInputStream(fileInputStream);
int magic = input.readInt();

Enemy enemy = null;
if (GOOMBA_MAGIC == magic) {
   String json = input.readUTF();
   enemy = mapper.readValue(json, Goomba.class);
}

As far as if JSON is the right serialization to use, it's up to you. 至于JSON是否适合使用正确的序列化,则取决于您。 The things that are nice about it is it's human readable and editable. 关于它的好处是它是人类可读和可编辑的。 There are other serialization technologies if performance or disk usage are more important to you. 如果性能或磁盘使用率对您更重要,则还有其他序列化技术。 For something like this, JSON seems fine. 对于这样的事情,JSON似乎很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM