【问题标题】:How to read/write 3-dimensional information from/into multiple files?如何从多个文件读取/写入3维信息?
【发布时间】:2014-07-15 13:57:05
【问题描述】:

我想将我的地图存储到多个文件中,以便稍后获取这些数据。该地图是一种无限的、噪声生成的地图。地图被切成小块。噪声生成参数具有种子值 + XYZ,因此我可以轻松地再次重新生成相同的块。每个块都有自己的 c# 脚本,该脚本具有 3 维字节数组 map[x,y,z],该值将告诉我哪个块属于该点。 XYZ 坐标是世界坐标而不是块坐标,这意味着即使我将它们全部组合在一起,也不会有相同的 map[x,y,z] 值。

我希望这个应用程序也可以在移动平台上使用,所以我想在我的应用程序专用服务器中生成地图,并在请求时通过网络发送块数据。虽然这减少了客户端的 CPU 使用率,但它也为我提供了额外的安全性来抵御黑客攻击。 (我可以检查玩家是否有效加载区块,玩家将无法扫描整个地图并查看所有好东西在哪里等)

我阅读了有关将多维字节数组存储到文件中并稍后从中读取的信息。我可以轻松获取块 XYZ 位置并将其放入文件名中,以便例如将块 0,0,0 数据写入 chunk_0_0_0.chunk 文件。我可以将块数据存储到文件中,因为我知道块的大小及其位置。

这是我目前未经测试的代码:

            // Check if chunk 0,0,1 exists, if not then nothing has been yet generated!
            if(!File.Exists("world\\chunk_0_0_1.chunk")){
                generateChunk(0,0,1);
                saveMapToFile();
            }

            foreach (string file in Directory.EnumerateFiles("world\\", "*.chunk"))
            {
                BinaryFormatter formatter = new BinaryFormatter();
                using (FileStream stream = new FileStream("world\\" + file, FileMode.Open, FileAccess.Read))
                {
                    byte[,,] tempArray = (byte[,,])formatter.Deserialize(stream);
                }
            }
            return true;

我有一个字节(public static byte[,,] map; map[0,0,1] = 0; map[0,1,1] = 4; 等),我想在其中存储每个块数据,以便客户可以轻松获取一张地图及其类型。由于这是无限的地形,当玩家探索更多时,地图会超时。由于我无法调整字节大小并为其添加更多值,因此我需要其他东西。我需要一些可以存储每个块位置及其值的东西。我不能使用列表或字典,因为它们不支持 3 维。我需要一些可以改变价值观的东西,因为玩家将改变世界。问题是:什么?

【问题讨论】:

  • 块内 x,y,z 的取值范围是多少?我是否也正确理解您为每个位置存储 1 个字节的数据?

标签: c# arrays


【解决方案1】:

您可以简单地将块类型字节按 x、z、y 顺序存储在常规字节数组中。然后,您可以通过其坐标获取数组中任何块的索引。一旦你有了数组的索引,你就可以使用索引获取和设置块类型值。这是一个例子:

public class Chunk
{
    // Maximum values for directions within a chunk.
    // Change these to suit your implementation
    private static readonly byte _xLength = 32;
    private static readonly byte _yLength = 32;
    private static readonly byte _zLength = 32;

    private byte[] _buffer;

    // For creating a brand new Chunk
    public Chunk()
    {
        _buffer = new byte[_xLength * _yLength * _zLength];
    }

    // Used by Load();
    private Chunk(byte[] buffer)
    {
        _buffer = buffer;
    }

    // Loads a Chunk from file
    public static Chunk Load(string filePath)
    {
        return new Chunk(File.ReadAllBytes(filePath));
    }

    // Saves the Chunk to file
    public void Save(string filePath)
    {
        File.WriteAllBytes(filePath, _buffer);
    }

    // Gets a value in the buffer for coordinate 
    public byte GetBlock(byte x, byte y, byte z)
    {
        int offset = GetOffset(x, y, z);

        return _buffer[offset];
    }

    // Sets a value in the buffer for coordinate 
    public void SetBlock(byte x, byte y, byte z, byte value)
    {
        int offset = GetOffset(x, y, z);

        _buffer[offset] = value;
    }

    // Get the location in the buffer for coordinate
    private static int GetOffset(byte x, byte y, byte z)
    {
        return (y * _xLength * _zLength) + (z * _xLength) + x;            
    }
}

然后是一些测试..

static void Main()
{
    // Create a new Chunk
    Chunk chunk1 = new Chunk();

    // Set some block types in the chunk
    chunk1.SetBlock(1, 1, 1, 11);
    chunk1.SetBlock(2, 2, 2, 22);
    chunk1.SetBlock(3, 3, 3, 33);

    // Save it to disk
    chunk1.Save("test.chunk");

    // Load from disk
    Chunk chunk2 = Chunk.Load("test.chunk");

    Console.WriteLine("Block at ({0},{1},{2}): {3}", 1, 1, 1, chunk2.GetBlock(1, 1, 1));
    Console.WriteLine("Block at ({0},{1},{2}): {3}", 2, 2, 2, chunk2.GetBlock(2, 2, 2));
    Console.WriteLine("Block at ({0},{1},{2}): {3}", 3, 3, 3, chunk2.GetBlock(3, 3, 3));

}

【讨论】:

    猜你喜欢
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多