"无限"世界问题

时间:2011-12-15 04:58:16

标签: c# xna buffer infinite minecraft

我正在xna中创建一个类似于体素引擎的魔兽世界,并开始实施“无限”世界,但遇到了一些问题。一个这样的问题是,以下行总是似乎应用了反对者(例如,如果玩家移动X + REGION_SIZE_X,它将分配Direction.X_DECREASING而不是预期的Direction.X_INCREASING)。

    Thread regionLoader;

    public void CheckPlayer()
    {
        Direction direction = Direction.MAX;

        float distancetraveledx = player.Origin.X - player.Position.X;
        float distancetraveledy = player.Origin.Y - player.Position.Y;
        float distancetraveledz = player.Origin.Z - player.Position.Z;

        if (distancetraveledx > Variables.REGION_SIZE_X)
        {
            direction = Direction.XIncreasing;
            player.Position = new Vector3(player.Origin.X, player.Position.Y, player.Position.Z);
        }
        else if (distancetraveledx < -Variables.REGION_SIZE_X)
        {
            direction = Direction.XDecreasing; 
            player.Position = new Vector3(player.Origin.X, player.Position.Y, player.Position.Z);
        }
        else if (distancetraveledz > Variables.REGION_SIZE_Z)
        {
            direction = Direction.ZIncreasing;
            player.Position = new Vector3(player.Position.X, player.Position.Y, player.Origin.Z);
        }
        else  if (distancetraveledz < -Variables.REGION_SIZE_Z)
        {
            direction = Direction.ZDecreasing;
            player.Position = new Vector3(player.Position.X, player.Position.Y, player.Origin.Z);
        }
        if (direction != Direction.MAX)
        {
            regionManager.direction = direction;

            regionLoader = new Thread(new ThreadStart(regionManager.ShiftRegions));
            regionLoader.Start();
        }
    }

所以这样做是检查玩家是否已经从它的原点移动了REGION_SIZE,如果有,则重置移动到该边界的位置的组件。

然后调用以下函数:

    public void ShiftRegions()
    {
        // Future and current arrays are to avoid moving elements twice (or maybe I am thinking about it in the wrong way...)
        future_regions = new Region[(int)Variables.RENDER_DISTANCE, (int)Variables.RENDER_DISTANCE, (int)Variables.RENDER_DISTANCE];

        for (short j = 0; j < future_regions.GetLength(0); j++)
        {
            for (short m = 0; m < future_regions.GetLength(1); m++)
            {
                for (short i = 0; i < future_regions.GetLength(2); i++)
                {
                    future_regions[j, m, i] = new Region(world, new Vector3i(new Vector3(j, m, i)));

                    switch (direction)
                    {
                            // This appears to work as XDecreasing
                        case Direction.XIncreasing:
                            // If it is not at the back
                            if (j != future_regions.GetLength(0) - 1)
                            {
                                // Make the regions look like they are scrolling backward
                                future_regions[j, m, i] = regions[j + 1, m, i];
                                future_regions[j, m, i].Index = new Vector3i((uint)j, (uint)m, (uint)i);
                                // In the next call the vertex buffer will be regenerated thus placing the "blocks" in the correct position
                                future_regions[j, m, i].Dirty = true;
                            }
                            // If it is the front most region to which the player is traveling ing
                            if (j == 0)
                            {
                                // New the region setting the Generated flags to false thus allowing it to be regenerated
                                future_regions[j, m, i] = new Region(world, new Vector3i(new Vector3(j, m, i)));
                            }
                            // If it is at the back of the regions
                            if (j == future_regions.GetLength(0) - 1)
                            {
                                //store region
                            }

                            break;
                        case Direction.XDecreasing:

                            break;
                    }
                }
            }
        }


        generator.build(ref future_regions);
        direction = Direction.MAX;

        this.regions = future_regions;
    }

这实际上会移动导致滚动效果的区域和出现在前面的新区域。这似乎不起作用。

我在思考实际上“移动”区域我可以分配不同的偏移量并移动到世界矩阵中但是当我这样做时,我只是得到一个蓝屏...

以下是代码的其余部分:

生成器类功能:

    public virtual void build(ref Region[,,] regions)
    {


        for (short j = 0; j < regions.GetLength(0); j++)
        {
            for (short m = 0; m < regions.GetLength(1); m++)
            {
                for (short i = 0; i < regions.GetLength(2); i++)
                {
                    OutputBuffer.Add("Generating...");

                    if (regions[j, m, i].Generated == false)
                    {
                        regions[j, m, i].Dirty = true;
                        regions[j, m, i].Generated = true;

                        for (short x = 0; x < Variables.REGION_SIZE_X; x++)
                        {
                            for (short y = 0; y < Variables.REGION_SIZE_Y; y++)
                            {
                                for (short z = 0; z < Variables.REGION_SIZE_Z; z++)
                                {
                                    regions[j, m, i].Blocks[x, y, z] = new Block();

                                    Vector3i relativeBlock = new Vector3i(new Vector3(x + Variables.REGION_SIZE_X * j, y + Variables.REGION_SIZE_Y * m, z + Variables.REGION_SIZE_Z * i));

                                    if (x == 0 || x == 16 || x == 32 || z == 0 || z == 16 || z == 32 || y == 0 || y == 16 || y == 32)
                                    {
                                        regions[j, m, i].Blocks[x, y, z].BlockType = BlockType.dirt;
                                    }
                                    else
                                    {
                                        regions[j, m, i].Blocks[x, y, z].BlockType = BlockType.grass;

                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

以及检查是否需要重建区域缓冲区的代码:

    public void Update(World world)
    {
        this.world = world;

        for (short j = 0; j < regions.GetLength(0); j++)
        {
            for (short m = 0; m < regions.GetLength(1); m++)
            {
                for (short i = 0; i < regions.GetLength(2); i++)
                {
                    if (regions[j, m, i].Dirty &&
                        regions[j, m, i].Generated)
                    {
                        regions[j, m, i].BuildVertexBuffers();
                    }
                }
            }
        }
    }

顺便说一下,如果Dirty设置为true,则表示需要重新生成缓冲区。

为什么这不是在前面创建新区域以及为什么它不能正确滚动的任何想法?

编辑:我只是逻辑思考,我改变阵列中区域位置的想法不会改变它的世界位置,就像我上面说的那样将它们转换到正确的位置而不是复制它们 - 这似乎是最合乎逻辑的一步。好吧,我可能需要将一些复制到区域数组中的不同位置,因为如果你只是转换它们,阵列很快就会成为意大利面......

谢谢,Darestium

1 个答案:

答案 0 :(得分:0)

只看这部分

float distancetraveledx = player.Origin.X - player.Position.X;

你从原点减去位置,你应该扭转顺序并执行此操作

float distancetraveledx = player.Position.X - player.Origin.X;

例如,如果玩家从(0,0,0)移动到(10,0,0),则玩家在X方向上移动了10个单位,但是你的'distancetraveledx'会给你0-10 ,或-10。

与您的问题无关: 如果您使用CamelCase,第一个字母为大写或大写,则您的变量将更易于使用:

float distanceTraveledX = player.Position.X - player.Origin.X;

在C#中,惯例是让首字母大写的类名,以及首字母小写的变量,如下:

MyClass myClass;