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
本文原发表在个人博客上。