2013-06-12 56 views
6

你曾經玩過「坦克大戰」遊戲嗎?「坦克大戰」遊戲中的隨機土地算法

enter image description here

我編程這個遊戲用JavaScript +帆布(爲個人挑戰),和我需要的是用於生成隨機綠地我每次啓動遊戲時間的算法,但我數學不太好,所以我不能自己做。

我不希望有人給我的代碼,我只想對算法的想法。

謝謝!

+0

僅供參考,我認爲如果你把你的心給它,你可以得到一個平滑的線條(exclipes?),圓polygins。完成後發佈鏈接到遊戲! – tgkprog

+0

@tgkprog我當然會! – user2479365

+0

爲了澄清這個問題:我需要的是一個算法,返回繪製土地和平滑它們的隨機點。 – user2479365

回答

5
enter image description here


(9段)

Fiddle demo

enter image description here
(7段)

主要生成功能是這樣的:

var numOfSegments = 9;      // split horizontal space 
var segment = canvas.width/numOfSegments; // calc width of each segment 
var points = [], calcedPoints; 
var variations = 0.22;      // adjust this: lower = less variations 
var i; 

//produce some random heights across the canvas 
for(i=0; i < numOfSegments + 1; i++) { 
    points.push(segment * i); 
    points.push(canvas.height/2.8 + canvas.height * variations * Math.random()); 
} 

//render the landscape 
ctx.beginPath(); 
ctx.moveTo(canvas.width, canvas.height); 
ctx.lineTo(0, canvas.height); 

calcedPoints = ctx.curve(points);   // see below 

ctx.closePath(); 
ctx.fillStyle = 'green'; 
ctx.fill(); 

curve()函數是生成基數樣條函數的獨立函數。在這裏,您可以修改它以存儲張力值以製造更多尖峯。您還可以使用生成的點作爲坦克在哪裏以及以何種角度移動的基礎。

爲基數樣條函數:

CanvasRenderingContext2D.prototype.curve = function(pts, tension, numOfSegments) { 

    tension = (tension != 'undefined') ? tension : 0.5; 
    numOfSegments = numOfSegments ? numOfSegments : 16; 

    var _pts = [], res = [], t, i, l, r = 0, 
     x, y, t1x, t2x, t1y, t2y, 
     c1, c2, c3, c4, st, st2, st3, st23, st32; 

    _pts = pts.concat(); 
    _pts.unshift(pts[1]); 
    _pts.unshift(pts[0]); 
    _pts.push(pts[pts.length - 2]); 
    _pts.push(pts[pts.length - 1]); 

    l = (_pts.length - 4); 
    for (i = 2; i < l; i+=2) { 

     //overrides and modifies tension for each segment. 
     tension = 1 * Math.random() - 0.3; 

     for (t = 0; t <= numOfSegments; t++) { 
      t1x = (_pts[i+2] - _pts[i-2]) * tension; 
      t2x = (_pts[i+4] - _pts[i]) * tension;  
      t1y = (_pts[i+3] - _pts[i-1]) * tension; 
      t2y = (_pts[i+5] - _pts[i+1]) * tension; 

      st = t/numOfSegments; 
      st2 = st * st; 
      st3 = st2 * st; 
      st23 = st3 * 2; 
      st32 = st2 * 3; 

      c1 = st23 - st32 + 1; 
      c2 = -(st23) + st32; 
      c3 = st3 - 2 * st2 + st; 
      c4 = st3 - st2; 

      x = c1 * _pts[i] + c2 * _pts[i+2] + c3 * t1x + c4 * t2x; 
      y = c1 * _pts[i+1] + c2 * _pts[i+3] + c3 * t1y + c4 * t2y; 

      res[r++] = x; 
      res[r++] = y;    
     } //for t 
    } //for i 

    l = res.length; 
    for(i=0;i<l;i+=2) this.lineTo(res[i], res[i+1]); 

    return res; //return calculated points 
} 
+1

謝謝!我將研究代碼並在我的遊戲中實現它。這是完美的 – user2479365

+1

@ user2479365沒問題。通過較小的調整更新答案/提琴,並顯示如何從樣條中獲取計算得出的點。 – K3N

+0

所以你確實想要代碼 – tgkprog

3

查找到柏林噪聲的產生,這與良好的平滑算法的結合可以產生一些不錯的地形,並且是相當快的。還有就是代碼繞過球網踢某處的參考版本,它應該爲你提供一個相當沉重的領先地位

+0

我找到了另一種方式,但是感謝Perlin Noise,我正在爲另一個項目尋找類似的東西。 +1 – user2479365

1

首先你需要一個點是隨機的Y(55,65之間);得到x = 0 所以這是綠色的原點,讓它保持爲x1,y1(x1總是0)。

然後你需要一個30到40之間的隨機整數。這是x2。和隨機Y,它的範圍是從Y1 + 8〜+ Y1 20

然後X3和原理相同Y3(可以稱之爲公式類型1)

現在,你需要先得到一個隨機要麼 - 1或1,這將是y4的方向。所以y4可以高於y3或更低...這將是公式類型2.

您需要保留一個新的y的最大值和最小值y,如果它跨越了那麼然後轉到另一個方向 - >這會是修正式公式3.

Xn不斷增加,直到其> =板的寬度。

加入在日食的線條......看起來像網頁搜索是要走的路!

1

我確定有很多編碼庫可以用來實現這一點。但是如果你想自己編碼,這是我的想法。

您需要定義其他地方的地形。因此,您的環境的每個部分都是一個集羣。您需要定義如何通過節點(點)來分隔這些羣集。

您可以從一系列的點創建多邊形,而這個多邊形可以成爲任何你想要的,在這種情況下地形。

見你傳遞的圖像上,有波峯,那些節點(點)。請記住在您的環境邊界上定義節點。

1

肯定有一種新穎的書面算法,或者是@DesertIvy指出的分形或其他,或許也有圖書館,但是如果你想要生成圖片中的內容,它可以是非常簡單的,因爲它只是(稍微彎曲)點之間的線。如果分階段做,不是要正確一次,很容易:

  1. 拆分x區域的遊戲畫面的段(與一些最大和最小寬度)使用隨機的(你可能會稍微偏離在上一節中,但我認爲這並不重要)。記住X-ES,其中部分滿足(包括遊戲畫面邊境的)
  2. 準備一些數據結構有Y-S以及,先前想起X-S。從leftmost.y = 0開始,slope = Math.random()-0.5;
  3. 生成每個下一未定義ý開始以1:right.y = left.y + slope * (right.x-left.x);以及更新斜率每個y後:slope += Math.random()-0.5;。現在不要打擾,如果這一切都適合遊戲屏幕。
  4. 如果你想弧線,你可以爲每個部分隨機代表多少線的中間被撞相比直線「彎曲度」參數。
  5. 裝上YS進入遊戲屏幕:首先找到最大和最小生成Y(mingenymaxgeny)(可以跟蹤此而在點4生成)。選擇遊戲屏幕上的最大和最小y(minscry,maxscry)(比如說排名第四位和排名第四位)。然後轉換生成的ys,使其跨越minscrymaxscry之間:對於每個點,請執行apoint.y = minscry + (maxscry-minscry)/(maxgeny-mingeny)*(apoint.y-mingeny)
  6. 現在使用[x,y]點之間的線條作爲地形,如果要使用「曲線」,則需要將curvemodifier添加到y中,以便在leftx和rightx之間的區域中的任何特定x。弧不需要是一個圓:我會建議容易產生的拋物線或餘弦:var middle = (left.x+right.x)/2; var excess = (x-left)/(middle-left);,然後var curvemodifier = curviness * (1-excess*excess);var curvemodifier = curviness * Math.cos(Math.PI/2*excess)
+0

這是很長的,+1的努力,但我找到了一個更簡單的方法^^ 無論如何,謝謝。 – user2479365

1

哇......有一點我是完全沉迷於坦克大戰

既然你是一個學習的冒險...

您也可以瞭解context.globalCompositeOperation。

這畫布操作會讓你搶實際草的圖像,然後合成到你的遊戲。

您可以通過更改drawImage()的x/y來隨機化草的外觀;

是的,實際的草可能太分散注意力,不包括在你完成的遊戲中,但瞭解合成將是寶貴的知識。

...和+1的問題:在挑戰自己好樣的!

+0

什麼!?沒有小提琴? :P – Jarrod