2013-08-05 70 views
-1

這是我的方法來找到我的世界的自由空間。世界由可碰撞和不可碰撞的塊組成。我不希望暴徒在可以碰撞的方塊中產卵,因爲他們不能移動。但是,這種方法無法正常工作,我該如何改進它以使代碼實際上在自由空間中產生所有小怪?更高效的羣體產卵算法

所有的塊都是隨機生成的。

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. 
} 

此代碼有效。但是有些怪物會以塊狀產生。我希望所有隨機生成的小怪都不會在實體模塊中產生。

+4

您是否擔心效率或效果?在我看來,我們應該弄清楚它爲什麼不起作用,而且我們幾乎肯定沒有足夠的信息。 – ChrisCM

+0

原始代碼有效。然而,在一個固體塊中產生1或2個怪物通常是個例外。我想讓這100%準確,因爲所有的地形都是隨機生成的。 – Jadd23

+1

看看我的編輯。問題是,儘管遞歸,你仍然返回原來的xx值。我的編輯從基本的功能角度來修正你的代碼。簡單地留下效率問題。 – ChrisCM

回答

1

您的問題是,當再次調用該方法時,您永遠不會更改xx的值,因此它始終保持爲第一個值。將if (getBlock(xx, 0).solid()) findSpawnX(limit);更改爲 if (getBlock(xx, 0).solid()) xx = findSpawnX(limit);將起作用。

+0

是的,我已經嘗試過,但是,它給了我一個StackOverflowError。 – Jadd23

+1

這當然不是你的stackOverFlow錯誤的原因。這個答案只是解決了你的代碼問題,這就是說,如果你的第一個調用找到解決方案,它將不可避免地發揮作用,否則你會遞歸地調用,只是返回你找到的第一個值,如果你遞歸調用,是垃圾你不想要的價值。 – ChrisCM

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; 
} 
+0

這種方法也適用,但如果你不幸,不斷尋找一個隨機數可能會導致更多的搜索。我會說這個答案vs我的依賴於找到一個封鎖廣場的機會百分比。 – ChrisCM

0

我會做的是得到你的隨機座標,然後用它作爲你的位置的種子。假設該位置是有效的(未被阻止)返回它。否則,以螺旋形展開,迭代地檢查圓形螺旋圖案中的塊。在2-d空間,你可以在此順序檢查塊:

XXXXXXXXXX 
XXXX543XXX 
XXXX612XXX 
XXXX789XXX 
XXXXXXXXXX 

一發不可收拾,直到找到一個空的塊,在你的遊戲世界中類似的相對位置。再次,這是假設你的一般方法論是有效的,唯一的問題是如果它發現一個阻塞的座標,它沒有處理這種情況。假設我強烈建議你徹底測試一下!

0

雖然我不明白「並將其除以16以將其對齊到塊。」你的代碼中主要的低效率是不必要的遞歸調用(你的方法調用它自己)。這可以持續很長一段時間,方法自稱,自稱,然後自稱...

使用,而不是一個循環:

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

地圖中的所有組件都由16 * 16像素塊組成。我正在計算像素方面的所有內容,然後根據遊戲塊來轉換它們。 – Jadd23

+0

而這是一個很好的解決方案。暴徒仍然在塊內產卵。 – Jadd23

0

我會想象有一個與你的任何固體方法的問題或getBlock方法,如果沿着x進行迭代(假設至少有1個空閒塊/平鋪塊)不起作用,那麼它必須是如何檢索塊的錯誤,或者這是一個固體問題。

//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; 
} 

我對此事的看法是,你(否則承擔一切正常應該)要實現使用初始位置(X,Y)作爲種子在某些模式更有效地遍歷一個findSpawn/trySpawn程序在關卡中找到重生位置。沿着兩個軸而不僅僅是一個。

另一個注意事項:我經常看到的是getBlock/getTile程序在執行分割以減少源代碼的其他部分中的代碼量並提高可讀性..您可能需要牢記這一點。

希望有所幫助!