zz85在這裏用簡單的代碼就生成了一張隨機的城市地圖。生成地圖與畫一棵隨機的樹十分類似,都是先給出初始的元素,每一個元素在知足條件時會生成新的子代,最後由全部的元素共同組成了咱們想要的地圖或樹。git
地圖中的每一條道路對應程序中的一個Boid對象,Boid對象中用兩個向量分別表示道路的起點和終點座標。程序中的向量是使用 Three.js 這個庫中的Vector2
對象來表示的。github
// 使用three.js中的向量來表示 this.start = new THREE.Vector2(x, y); this.end = new THREE.Vector2(x, y);
Boid對象還有這些屬性:segmentfault
x,y
:道路上距離起點最遠的座標數組
angle
:道路的角度,會在其父代角度基礎上偏轉一個隨機的角度dom
distance
:這條道路的長度函數
dead
:對象是否已經死亡ui
Boid還有一個update
方法,它有以下的幾個功能:this
更新 x,y 座標spa
this.distance += 2;
x = this.start.x + this.distance * this.dx;
y = this.start.y + this.distance * this.dy;
this.end.set(x, y);.net
檢測相交狀況,根據更新後的座標做圖。
在程序中須要建立兩個數組用於保存Boid
對象,boids
中存放當前存活的元素,all_boids
存放全部(包括存活和死亡)的元素。產生一個新元素時,會被同時放入兩個數組,當元素死亡後,將其從boids
中移除。
對於一條道路A,它會一直向前延伸,直到與另外一條道路相交,這時將A的狀態設置爲dead。爲了檢測相交,須要對all_boids
數組中的元素進行遍歷。若是與其中的元素B出現了交點,多是如下幾種狀況:
A是B的子代
B是A的子代
B的終點在A上
A在延伸過程當中趕上了B
這最後一種狀況纔是咱們所須要的,將交點座標賦給A的終點,將A從boids數組中刪去。以上檢查交點的過程發生在update()函數中。
在程序開始時,首先建立四個元素來表示畫面的邊框。
var b1 = new Boid(); var b2 = new Boid(); var b3 = new Boid(); var b4 = new Boid(); b1.dead = b2.dead = b3.dead = b4.dead = true; b1.start.set(0, 0); b2.start.set(width, 0); b3.start.set(width, height); b4.start.set(0, height); b1.end = b2.start; b2.end = b3.start; b3.end = b4.start; b4.end = b1.start; all_boids.push(b1); all_boids.push(b2); all_boids.push(b3); all_boids.push(b4);
而後建立第一個boid
,它的座標在畫面的中間
var b = new Boid(width/2, height/2, Math.random() * 2 * Math.PI); boids.push(b); all_boids.push(b);
調用setInterval
函數進入循環,首先檢查boids.length
,若是當前沒有存活的boid
,則退出循環,程序完成。不然遍歷全部存活的Boid
,更新其狀態。在知足以下的幾個條件時生成子代。
沒有死亡
只有0.1的機率產生子代
當前全部存活元素的數量小於50
for (i = 0; i < boids.length; i++) {
var b = boids[i]; b.update(); // 產生子代的幾個條件: // 1. 沒有死亡 // 2. 只有0.1的機率產生子代 // 3. 當前全部存活元素的數量小於50 if (!b.dead && Math.random()>0.9 && boids.length < 50) { var child = new Boid(b.end.x, b.end.y, b.angle + Math.PI * (Math.random() > 0.5 ? 0.5 : -0.5)); child.parent = b; // child.fillStyle = getRndColor(); boids.push(child); all_boids.push(child); }
}
最終當存活的Boid數量爲零時,程序運行完畢,就獲得了一張隨機的城市道路地圖。固然,如今的地圖還只是 2D 的版本,想生成 3D 的城市,能夠查看下面的參考資料中zz85的博客。
在線的 demo
本文原發表在個人博客上。