“Infinite"世界问题
本文关键字:世界 问题 quot Infinite | 更新日期: 2023-09-27 18:17:50
我正在xna中创建一个像《我的世界》这样的体素引擎,并且已经开始执行"无限"世界,但遇到了一些问题。其中一个问题是,下面的一行似乎总是应用相反的内容(例如,如果玩家移动X+ REGION_SIZE_X,它将分配方向)。x_递减而不是预期的direction . x_递增)。
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
看看这部分
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;