【问题标题】:Loading and saving a tile based game in Java. XML or TXT?在 Java 中加载和保存基于图块的游戏。 XML 还是 TXT?
【发布时间】:2009-07-06 20:46:18
【问题描述】:

一段时间以来,我一直在制作基于 2d 瓷砖的模拟游戏,并且进展顺利!感谢这个网站和它的好心人(你!),我刚刚完成了游戏的寻路部分,太棒了!谢谢!...无论如何,问题。

目前,测试关卡是硬编码到游戏中的。显然我需要重新处理这个。我的想法是以各种方式将我的 Game 类中的所有变量保存到文本文件中。我还可以将每个级别的详细信息写入要为一个级别加载的文件中。我的问题是,我应该只使用文本文件还是使用 XML?我基本上了解 XML 是什么,但我真的不知道如何将它与 JAVA 结合使用,或者为什么它比纯文本文件更可取。 我有一点谷歌,有关于 XML 和 JAVA 的整本书!我看不出我需要知道关于如何使用 XML 和 JAVA 来完成这项工作的一切,但我确实需要知道的比我做的更多。

在此先感谢您的帮助。

编辑: 我将在这里尝试几种想法,直到找到最有效的想法,然后将其选为答案。

编辑:选择 xStream。简单易行!

【问题讨论】:

  • “有人说XML就像暴力一样,如果一点不能解决问题,那就多用一点。”
  • 100% ack,如果你使用 XML,请避免使用 43...
  • @Relequestual 你会感到惊讶。 XML 似乎激发了大量的字节浪费。
  • 实际上,完全使用这种格式可能有很好的理由。例如,如果您想对您的 XML 执行 XML Schema 验证,以确保每个 tile 元素的 x 和 y 属性都是预设范围内的整数,您可以。
  • 当您可以通过使用 XML 解析器为自定义文件格式编写和调试解析器节省时间时,谁他妈的关心浪费的字节?好像该游戏不会有数百万个图块。高清空间很便宜。如果您真的担心几百 K,请使用压缩。

标签: java xml tiles


【解决方案1】:

对于基于 2D 瓷砖的游戏,XML 可能是多余的。 XML 非常适合存储分层数据和/或标记文本,但听起来您只需要一种编码 2D 平铺设置网格的方法,这对于普通的旧文本文件来说要容易得多。

只需将每一行设为一排图块,然后决定每个图块需要多少个字符(可能一两个就可以了)。然后决定如何用文本文件中的字符来表示 2D 世界中的对象。

SokoBean(我在 10 多年前写的游戏,所以不是我称之为我最好的作品,但无论如何)我使用了text files like this one。除了比 XML 更容易解析之外,您还可以使用普通的旧文本编辑器作为关卡编辑器。

【讨论】:

  • 感谢这个有趣的小游戏!我认为我无法为如此复杂的游戏实现相同类型的文本文件。这是我使用任何编程语言的第二个游戏,所以我在学习过程中学到了很多东西!
【解决方案2】:

您将文件用于内部目的。简短的回答是,只要文件格式符合您的目的,就可以了。你确实想尽你所能来确保格式清晰、尽可能简单和可扩展。这里最重要的一点是将读取和写入的数据提取到代码中负责读取和写入文件格式的单个点。

常见格式很常见,因为它们简单且支持良好 - 您无需编写特殊代码来解析文件(属性文件,基本上只是键值对列表和 xml 文件 - 想想 xml文件作为编写任意深度嵌套字典的一种方式)。

【讨论】:

  • 谢谢。我知道如何从文本文件中读取数据,在过去一年左右的时间里一直在学习。事情我建立这样一个文件,保存它然后再次加载它没有问题......我希望。
【解决方案3】:

这当然取决于你的需求,但是 XML 格式给你带来了很多好处,我可能会在这样的项目中自己选择 XML。

  • 可以自动 通过工具检查/验证 确保它是正确的并根据 你设置的规则。
  • 现有的 Java 库可用于 解析、读取和更新 XML 文档。
  • 该格式很容易为您的程序的未来版本扩展,但仍然易于保持向后兼容性
  • 如果文件是 XML 而不是一些特别改编的文本格式,其他人很容易阅读和理解您的文件

【讨论】:

    【解决方案4】:

    如果它是纯粹的基于图块的游戏,那么纯文本文件可能是要走的路。

    您可能需要固定宽度的整数,每行后用换行符用空格分隔。无需 XML 库即可轻松阅读和解析。

    编辑:

    一条重要的建议:

    无论你决定做什么,封装它!制作一个读取器接口,该接口接受通用输入流并返回(或填充)您的网格结构。有一个写入器接口,它采用网格结构和通用输出流并将数据转储到该输出流。如果您以后改变了对如何实现文件的想法,或者如果您想添加网络播放等,您会感谢自己的。

    【讨论】:

    • 是的,我想我同意你的看法。我正在和一个建议 XML 的朋友讨论这个问题,只是想看看 Stack 对此有什么看法。
    【解决方案5】:

    就您自己的东西,尤其是游戏而言,XML 被高估了。如果您在一家大公司工作,其他人需要查看您文件的文本,那么 XML 可能 是有意义的,但即使在这种情况下,您也可能会编写一个关卡编辑器来完成所有操作你。

    我建议使用您自己的约定的简单文本文件,或者使用java.io.ObjectOutputStream 和 java.io.ObjectInputStream 将数据直接写入数据文件(如果您有很多信息或对象)或@ 987654323@ 来写你的数据(如果你只需要写原语)。

    上面很多人都提到 XML 有多好,因为它具有“自动序列化”,但我真的认为在 Java 中工作时不值得一提,因为我上面列出的两种方法也是自动的,但是在更高级的水平。

    另外不要忘记,使用 XML 标签表示 2D 瓦片地图非常不直观,而在字符文件中逐行写入它们是相当容易读写的。

    例如)

    WWWWWWWWWW  
    WSWWWWW EW  
    W W K WW W  
    W W   WW W  
    W WW WWWDW  
    W  X     W  
    WWWWWWWWWW  
    

    你可以像上面那样做,W 是墙,S 是开始,E 是出口,K 是钥匙,D 是门,X 是怪物.一切都在哪里以及应该如何设置关卡非常明显,即使是文本文件也是如此。

    我在许多专业游戏项目中都使用过文本文件。事实上,我只是在为某人完成承包工作时才使用 XML,因为 XML 看起来“更专业”,尽管在大多数情况下它是不必要的,而且只是浪费空间,使事情变得过于复杂。

    另一个例子:

    SpawnFrequency 0.1 20.5
    HealthPoints 5
    Stats 12 500 30 10 11  
    

    您可以想象可能发生的任何其他事情。然后,当您将文件读入 Java 时,只需使用 BufferedReader.readLine() 获取每个参数,然后使用 String.split() 获取该参数的所有值的数组。然后,比较拆分数组中的第一个值的大型 switch 语句或 if/else 分组将确定您实际读取的参数。当您达到这一点时,您就接近了 XML 的用处,但是对于这种用途,它仍然可能过于臃肿。然而,XML 可以帮助解释其中一些神秘的值可能是什么:

    XML 中的上述内容:

    或者可能是这样的:

    `<GuyStuff>`  
        `<SpawnFrequencyMinimum>0.1</SpawnFrequencyMinimum>`  
        `<SpawnFrequencyMaximum>20.5</SpawnFrequencyMaximum>`  
        `<Health>5</Health>`  
        `<Strength>12</Strength>`  
        `<Agility>500</Agility>`  
        `<Stamina>30</Stamina>`  
        `<TechnoWizardry>10</TechnoWizardry>`  
        `<JavaSkillz>11</JavaSkillz>`  
    `</GuyStuff>`  
    

    但是,当您再次开始遇到这种复杂性时,您不妨开始使用java.io.Serializable,因为它非常简单。

    编辑 这是一个可序列化的示例。

    public class MySaveData implements java.io.Serializable //Serializable doesn't need any methods implemented, it simply says, "hey Java, my object can be written to a file."
    {
        float data1;
        int data2;
        Object data3;
        //BufferedImage data4; //Note that in order for an object to serialize, it can't contain any data members that are not Serializable, so this would be illegal.
    }
    
    import java.io.*;
    public class DataReader
    {
        public void saveData(File loc, MySaveData obj1, MySaveData obj2, MySaveData obj3)
        {
            try
            {
                //You can use any type of OutputStream to create an OOS, so you can for
                //example use one when you're connected with Sockets or something similar.
                ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(loc));
    
                //Writing objects is tremendously easy, and so are primitives.
                //Note that the order you write them in is the same order you will read them.
                os.writeObject(obj1);
                os.writeObject(obj2);
                os.writeObject(obj3);
                os.writeDouble(someValueINeededToWrite);
                os.close();
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    
        public void loadData(File loc, PlaceToPutData place)
        {
            try
            {
                //ObjectInputStream follows the same rules as OOS mentioned above.
                ObjectInputStream is = new ObjectInputStream(new FileInputStream(loc));
    
                //Remember to read your data back the same order you wrote it.
                place.obj1 = is.readObject();
                place.obj2 = is.readObject();
                //If you don't want one of the objects for some reason and want
                //to get something after it, you can just read the next one but not use it.
                readObject();
                place.value = is.readDouble();
                is.close();
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    }
    

    您的文件通常是这样的:new java.io.File("/Documents/MyGame/MyDataFile.whateverIFeelLikeAsLongAsItsConsistent")

    【讨论】:

    • 我只用过java.io.outputstream和inputstream。我对java还是很陌生,所以还没有听说过你提到的其他人,所以不知道它们是什么或如何使用它们。我现在必须调查他们!如果我在对象中的对象等中拥有自己的对象,并且在单个主游戏类对象中拥有所有游戏变量,我是否能够像您所说的那样使用可序列化?
    【解决方案6】:

    如果您在一个对象(例如 HashMap,或者可能是您自己设计的对象)中拥有游戏状态,那么您可以使用XStream 将其写为 XML 文件,然后将其读回再次使用 XStream 的新对象。

    有一个two minute tutorial 向您展示如何序列化/反序列化。它可以毫无困难地处理大多数对象——您不需要实现或指定任何特定的接口。也不需要 JAXP、SAX、DOM 等。

    【讨论】:

    • 哇,这看起来真的很有趣!如果它像你说的那样有效,我想这可能就是答案!我的意图是将所有内容都包含在我创建的名为 Game 的对象中。
    • 应该可以的。我遇到的唯一问题是 w.r.t 序列化内部类,此时它会爆炸。但除此之外,它是相当微不足道的
    • 我不确定你所说的 w.r.t 序列化内部类是什么意思...你能解释一下吗?
    • 如果你序列化一个内部类,就会有一个对外部类的隐式(隐藏)引用。因此,当您序列化内部类时,序列化程序也会尝试序列化外部类(这不是您所期望的)。如果您无意中尝试序列化您认为是外部但实际上是(内部)的东西,它只会让您感到困惑。
    • 好的,感谢您的解释。我一直在阅读序列化。我是否理解如果我使用我制作的对象类,它不能自动序列化?我是否必须为我希望使用的每个类添加方法?还是 XStream 的全部意义在于您可以使用自己的对象而无需编写序列化代码?
    【解决方案7】:

    这取决于您需要保存多少数据,以及您需要如何检索它。

    XML 可以很容易地转换为带有多个库的 java POJO,因此这是一个优势。此外,您会发现它易于学习和使用,只需尝试一些教程即可。

    但如果你需要保存大量数据,你可以考虑使用嵌入式数据库,或者单独的 sql server,这取决于你的应用程序。

    【讨论】:

    • 真正保存的数据并不多,它是一款基于 2D 瓷砖的小型模拟游戏。
    【解决方案8】:

    如果您是唯一要修改文件的人,请使用您想要的任何格式。但是,如果您希望用户或测试人员或其他人修改它,请使用 XML。 XML 的一大优势是它是一种标准格式,很多人(甚至很多非程序员)都知道如何编写代码。

    【讨论】:

      【解决方案9】:

      我只在需要 XML 生态系统的某些部分时才考虑使用 XML:验证、转换、自动序列化/反序列化等。但我知道所有这些东西是什么,而且我知道如何使用它们来达到很好的效果.

      如果你不这样做——从这个问题的主旨来看,我猜你不这样做——那么真正的问题是“我应该学习所有这些东西,以便可以将我的信息保存在 XML 文档中吗? "答案是“你几乎肯定不应该”。

      【讨论】:

        【解决方案10】:

        您可能会考虑使用 JavaDB 等嵌入式数据库,该数据库位于此处: http://developers.sun.com/javadb/

        嵌入它只有 2.5MB,您可能会发现以结构化、可靠的方式保存各种数据的能力非常有用。

        您可以使用诸如 Hibernate 之类的 ORM 框架来处理数据,但这对您的应用程序来说可能是多余的。您可以改用直接的 JDBC。

        祝你好运,玩得开心。

        【讨论】:

          【解决方案11】:

          作弊有问题吗?如果是这样,那么无论输出以某种方式,我都会加密。如果不是,则以纯文本形式输出。

          就格式而言,我会使用 XML。你可以做类似的事情

          <Map>
              <Tile x="1" y="1" value="2"></Tile>
              <Tile x="1" y="2" value="1"></Tile>
              <Tile x="1" y="3" value="7"></Tile>
              ...
          </Map>
          

          这将提供一种很好的可读格式,并且可以存储相当多的数据。

          【讨论】:

          • 作弊目前没有问题。如果最终成为问题,我可以在保存之前加密 xml。
          【解决方案12】:

          我使用一个类(实现 java.io.Serializable)来存储游戏统计信息。 然后我使用 ObjectOutputSteam 将该类写入文件。 要加载该类,您可以使用 ObjectInputStream。

          马丁

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-12-02
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多