一种更有效的mob产卵算法

时间:2013-08-05 15:44:32

标签: java game-engine

这是我在我的世界中寻找自由空间的方法。世界由可碰撞和不可碰撞的块组成。我不希望怪物在可碰撞的块中产生,因为它们无法移动。但是,这种方法不能正常工作,我如何改进它以使代码实际上在自由空间中产生所有怪物?

所有块都是随机生成的。

public int findSpawnX(int limit) {
    int xx = random.nextInt(limit) / 16; //find a random x coordinate and divide it by 16 to snap it to a block.

    if (getBlock(xx, 0).solid()) findSpawnX(limit); //check if xx is at a solid block, if so then redo the method.
    return xx; // if it is not solid then return the coordinate.
}

此代码有效。但是一些小怪在街区产卵。我希望所有随机产生的怪物都不会在固体块中产生。

5 个答案:

答案 0 :(得分:1)

您的问题是,在再次调用该方法时,您永远不会更改xx的值,因此它始终作为第一个值保留。将if (getBlock(xx, 0).solid()) findSpawnX(limit);更改为 if (getBlock(xx, 0).solid()) xx = findSpawnX(limit);会奏效。

答案 1 :(得分:1)

在失败时递归调用函数不是很好的编码(除了the problem with your code)。而是采用迭代方法:

public int findSpawnX(int limit) {
    int xx;
    do
    {
       xx = random.nextInt(limit) / 16;
    }
    while (getBlock(xx, 0).solid());
    return xx;
}

答案 2 :(得分:0)

我要做的是获取随机坐标,然后将其用作您职位的种子。假设该位置有效(未被阻止)返回它。否则以螺旋形扩展,以迭代方式检查圆形螺旋图案中的块。在二维空间中,您可以按以下顺序检查块:

XXXXXXXXXX
XXXX543XXX
XXXX612XXX
XXXX789XXX
XXXXXXXXXX

直到找到一个空块,然后在游戏世界中具有相似的相对位置。同样,这假设你的一般方法是有效的,唯一的问题是,如果它找到了一个被阻塞的坐标,它就没有处理这种情况。一个假设我强烈建议你彻底测试!

答案 3 :(得分:0)

虽然我不理解“并将其除以16以将其捕捉到块。”代码中的主要低效率是不必要的递归调用(您的方法调用自身)。这可以持续很长时间,一个调用自身的方法,调用自身,然后调用自己......

改为使用循环:

 while(getBlock(xx, 0).solid()) {
     xx = random.nextInt(limit) / 16;
 }

答案 4 :(得分:0)

我认为你的solid方法或getBlock方法存在问题,如果沿x迭代(假设至少有1个空闲块/ tile)不起作用那么它必须是你如何检索它的错误块,或者它是固体的问题。

//may go into an infinite loop if all blocks along x are solid
//could be solved quite inefficiently by buffering the block positions
//in an array and also using this to prevent checking the same block twice
//or instead, you could iterate along x and check if there's a non-solid
//block and return its position.
//Assuming your levels are procedurally generated, this should be fine.
public int findSpawnX(int limit) {
    int xx = random.nextInt(limit) / blockWidth;
    while(getBlock(xx, 0).solid()) {
        xx = random.nextInt(limit) / blockWidth;
    }
    return xx;
}

我对此事的看法是你(假设其他所有工作都应该)应该实现一个findSpawn / trySpawn过程,该过程使用初始位置(x,y)作为种子以某种模式迭代以更有效地找到生成位置在水平。沿着两个轴而不仅仅是一个轴。

另一个注意事项:我经常看到的是getBlock / getTile程序执行分区,以减少源代码的其他部分的代码量并提高可读性。您可能需要牢记这一点。

希望在某种程度上有所帮助!