资讯专栏INFORMATION COLUMN

利用JavaScript生成一张随机的城市地图

wanghui / 911人阅读

摘要:在这里用简单的代码就生成了一张随机的城市地图。产生一个新元素时,会被同时放入两个数组,当元素死亡后,将其从中移除。以上检查交点的过程发生在函数中。

zz85在这里用简单的代码就生成了一张随机的城市地图。生成地图与画一棵随机的树十分相似,都是先给出初始的元素,每个元素在满足条件时会生成新的子代,最后由所有的元素共同组成了我们想要的地图或树。

程序中创建的几个对象

地图中的每一条道路对应程序中的一个Boid对象,Boid对象中用两个向量分别表示道路的起点和终点坐标。程序中的向量是使用 Three.js 这个库中的Vector2对象来表示的。

// 使用three.js中的向量来表示
this.start = new THREE.Vector2(x, y);
this.end = new THREE.Vector2(x, y);

Boid对象还有这些属性:

x,y:道路上距离起点最远的坐标

angle:道路的角度,会在其父代角度基础上偏转一个随机的角度

distance:这条道路的长度

dead:对象是否已经死亡

Boid还有一个update方法,它有如下的几个功能:

更新 x,y 坐标

this.distance += 2;
x = this.start.x + this.distance * this.dx;
y = this.start.y + this.distance * this.dy;
this.end.set(x, y);

检测相交情况,根据更新后的坐标作图。

在程序中需要创建两个数组用于保存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的博客。

代码及演示

我在GitHub上的代码地址

在线的 demo

参考资料

Making of Boids and Buildings

本文原发表在我的博客上。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/78456.html

相关文章

  • 使用JavaScript实现机器学习和神经学网络

    摘要:我会使用一个先进的神经网络和机器学习框架这个框架,并向你们展示如何用这个框架来实现光学字符辨识,模拟退火法,遗传算法和神经网络。欧氏距离我们从欧氏距离开始谈起,欧氏距离是一个非常简单的概念,适用于不同的机器学习技术。 欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 下载 heaton-javascript-ml.zip - 45.1 KB 基本介绍 在本文中,你会对如何使用Ja...

    tunny 评论0 收藏0
  • 浅谈前端安全

    摘要:安全问题的分类按照所发生的区域分类后端安全问题所有发生在后端服务器应用服务当中的安全问题前端安全问题所有发生在浏览器单页面应用页面当中的安全问题按照团队中哪个角色最适合来修复安全问题分类后端安全问题针对这个安全问题,后端最适合来修复前端安全 安全问题的分类 按照所发生的区域分类 后端安全问题:所有发生在后端服务器、应用、服务当中的安全问题 前端安全问题:所有发生在浏览器、单页面应用、...

    Cympros 评论0 收藏0
  • 浅谈前端安全

    摘要:安全问题的分类按照所发生的区域分类后端安全问题所有发生在后端服务器应用服务当中的安全问题前端安全问题所有发生在浏览器单页面应用页面当中的安全问题按照团队中哪个角色最适合来修复安全问题分类后端安全问题针对这个安全问题,后端最适合来修复前端安全 安全问题的分类 按照所发生的区域分类 后端安全问题:所有发生在后端服务器、应用、服务当中的安全问题 前端安全问题:所有发生在浏览器、单页面应用、...

    李世赞 评论0 收藏0
  • 浅谈前端安全

    摘要:安全问题的分类按照所发生的区域分类后端安全问题所有发生在后端服务器应用服务当中的安全问题前端安全问题所有发生在浏览器单页面应用页面当中的安全问题按照团队中哪个角色最适合来修复安全问题分类后端安全问题针对这个安全问题,后端最适合来修复前端安全 安全问题的分类 按照所发生的区域分类 后端安全问题:所有发生在后端服务器、应用、服务当中的安全问题 前端安全问题:所有发生在浏览器、单页面应用、...

    alexnevsky 评论0 收藏0

发表评论

0条评论

wanghui

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<