【问题标题】:How can I load selective data from a serialized object in Java?如何从 Java 中的序列化对象加载选择性数据?
【发布时间】:2016-11-24 02:28:08
【问题描述】:

我正在为一个学校项目编写一个 2-D RPG 风格、基于 sprite 的游戏,我们小组决定游戏应该有一个跟随玩家而不是固定的摄像头,这自然意味着游戏需要在玩家四处移动时动态加载世界数据。我知道这可以通过分块加载世界的各个部分来实现,就像在 Minecraft 中一样,但我希望能够有选择地和频繁地加载少量数据,而不是不那么频繁地加载大块数据。例如,玩家向上移动一个单位,因此游戏可以在加载顶行时从内存中丢弃底行数据,而不是加载整个块或不时卸载块。目前所有相关的世界数据都存储在二维数组中,那么有没有一种有效的方法可以从世界文件中加载数组中的特定数据点,而无需加载整个事物或大块加载?

再一次,也许大块加载是更好的选择,因为从硬盘加载需要更长的时间,有什么想法吗?

假设在这种情况下,我的世界文件由称为区域的较小文件组成,这些文件基本上是块。

那么我的问题是:“我将如何从主世界文件中加载这些特定区域而不立即加载整个内容?”

【问题讨论】:

  • 所以简而言之,您想将一个矩阵存储在一个文件中,然后您想从文件中随机访问一个子矩阵,而不需要遍历整个文件?
  • @WasiAhmad 基本上,是的。
  • 取决于文件格式。如果您可以以编程方式确定给定单元格的偏移量,则可以查找该偏移量并读取。如果不能(单元格大小可变),则必须索引序列化数据,使其成为单元格->偏移量。但是为此,是的,磁盘查找会杀死您,并且您可能会在内存中容纳整个世界。

标签: java arrays serialization


【解决方案1】:

你可以看到example,它主要用于存储巨大的矩阵,因为加载一个巨大的矩阵需要大量的内存。如果将矩阵存储在随机访问文件中,而不是加载到内存中,则可以非常快速地检索它们。您只需将矩阵映射到RandomAccessFile 以供以后使用。我不是在迭代整个示例,而只是迭代您需要清楚理解的主要部分,以便您可以根据需要重新实现它。

public long position(int x, int y) {
    return (long) y * width + x;         // returns the position of a value in the file
}

public double get(int x, int y) {
    assert x <= 0 && x > width;          // simply bound check
    assert y <= 0 && y > height;         // simply bound check
    long p = position(x, y) * 8;         // 8 for double, if integer then use 4
    int mapN = (int) (p / MAPPING_SIZE);
    int offN = (int) (p % MAPPING_SIZE);
    return mappings.get(mapN).getDouble(offN);
}

get 方法从存储在文件中的矩阵中的特定位置(行、列)检索值。 mappings 只是一个类似于 java 中的 list 的数据结构。像get 方法一样,您也需要一个set 方法。

public void set(int x, int y, double d) {
    assert x <= 0 && x > width;
    assert y <= 0 && y > height;
    long p = position(x, y) * 8;
    int mapN = (int) (p / MAPPING_SIZE);
    int offN = (int) (p % MAPPING_SIZE);
    mappings.get(mapN).putDouble(offN, d);
}

重要提示MAPPING_SIZE 可以设置为 1 &lt;&lt; 31 或更低的值,因为 Java 不支持 2 GB (2^31) 或更大的映射一次。因此,如果您使用 set MAPPING_SIZE = 1 &lt;&lt; 30,它会将文件分区为 1 GB 映射。为简单起见,您可以将其视为拆分一个大矩阵并将它们存储在小块中(这些称为映射)。如果你有一个小矩阵,那么你不需要担心它。

【讨论】:

  • 啊,谢谢,这正是我要找的东西!
  • @GregorySalazar 最好的感谢方式是接受答案并投赞成票 ;)
  • 对不起,我是新来的,我为你投票,但它说它不会显示,因为我的声誉还不够高
  • @GregorySalazar 您可以接受答案,因为您是问题的所有者:)
猜你喜欢
  • 2015-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-19
  • 2014-12-20
  • 2014-10-28
  • 2012-01-01
相关资源
最近更新 更多