概要
Boids 1.0で準備した枠組みに、分離(Separation)、結合(Cohesion)、整列(Alignment)のルールを適用していく。
Boids 1.1~分離の導入
個体が近づいたときに、互いに近づき過ぎないように速度を修正するルールを導入。
デモンストレーション
各個体が他の個体とぶつからないよう避けながらランダムに移動している。
グローバル定義部
個体同士が近づきすぎた場合の分離行動に入る最大距離を指定。
1 2 |
// 分離の動作を行う距離 var SEPARATION_DISTANCE = 40; |
Creatureクラス
分離行動は個体のmove()
メソッド内で実装し、相手との距離が大きいほど逆方向への力をかける。速度調整後、速さを初期設定の値にそろえる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
Creature.prototype.move = function() { var other; var d; var newV; this.x += this.vx * TIME_SLICE / 1000; this.y += this.vy * TIME_SLICE / 1000; // ルール:分離(Separation) for ( i = 0; i < creatures.length; i++ ) { if ( this != creatures[i] ) { other = creatures[i]; if ( this.distanceTo( other ) < SEPARATION_DISTANCE ) { this.vx -= other.x - this.x; this.vy -= other.y - this.y; } } } // 速さを最大値に調整 newV = Math.sqrt( this.vx * this.vx + this.vy * this.vy ); this.vx *= MAX_VELOCITY / newV; this.vy *= MAX_VELOCITY / newV // 左右の壁の反射処理 if ( this.x < 0 ) { this.x = 0; this.vx = -this.vx; } else if ( this.x > canvas.width ) { this.x = canvas.width; this.vx = -this.vx; } // 上下の壁の反射処理 if ( this.y < 0 ) { this.y = 0; this.vy = -this.vy; } else if ( this.y > canvas.height ) { this.y = canvas.height; this.vy = -this.vy; } } |
Boids 1.2~結合(Cohesion)の導入
分離に加えて、各個体が群として集まろうとするルール。具体には、群の中心に向かおうと速度を変更するルールを導入。
デモンストレーション
個体がランダムに移動しながら、群を形成しようとしている。
グローバル定義部
まず、群の中心をグローバル変数として保持。
1 2 3 |
// 結合(Cohesion)のための群の重心 var centerX; var centerY; |
中心に向かって速度を変更する度合いを定数で指定。この値が小さいほど素早く、大きいほどゆるやかに群れようとする。
結合とのバランスで、分離の判定距離を小さめの値に設定している。
1 2 3 4 5 |
// 結合(Cohesion)の速度変更度 var COHESION_RATE = 5; // 分離の動作を行う距離 var SEPARATION_DISTANCE = 20; |
群の中心の算出
各個体が目指す群の中心を、実行関数moveAll()
の中で計算する。ここでは、全個体の平均重心を群の中心としている。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
function moveAll() { // 結合(Cohesion)のための群の重心を求める centerX = 0; centerY = 0; for ( var i = 0; i < creatures.length; i++ ) { centerX += creatures[i].x; centerY += creatures[i].y; } centerX /= creatures.length; centerY /= creatures.length; for ( var i = 0; i < creatures.length; i++ ) { creatures[i].move(); } } |
Creatureクラス
結合行動も個体のmove()
メソッド内で実装する。群の中心に向かって行くよう速度を変更。
ルールの適用準は、衝突回避を後にするため、結合→分離の順としている。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
Creature.prototype.move = function() { var other; var d; var newV; this.x += this.vx * TIME_SLICE / 1000; this.y += this.vy * TIME_SLICE / 1000; // ルール:結合(Cohesion) this.vx += ( centerX - this.x ) / COHESION_RATE; this.vy += ( centerY - this.y ) / COHESION_RATE; // ルール:分離(Separation) for ( var i = 0; i < creatures.length; i++ ) { if ( this != creatures[i] ) { other = creatures[i]; if ( this.distanceTo( other ) < SEPARATION_DISTANCE ) { this.vx -= other.x - this.x; this.vy -= other.y - this.y; } } } // 速さを最大値に調整 newV = Math.sqrt( this.vx * this.vx + this.vy * this.vy ); this.vx *= MAX_VELOCITY / newV; this.vy *= MAX_VELOCITY / newV // 左右の壁の反射処理 if ( this.x < 0 ) { this.x = 0; this.vx = -this.vx; } else if ( this.x > canvas.width ) { this.x = canvas.width; this.vx = -this.vx; } // 上下の壁の反射処理 if ( this.y < 0 ) { this.y = 0; this.vy = -this.vy; } else if ( this.y > canvas.height ) { this.y = canvas.height; this.vy = -this.vy; } } |
Boids 1.3~整列(Alignment)の導入
一通りのBoidsの実装の最終段階。
各個体が、群全体の移動方向に合わせようとするルールを導入。各個体が、自分の速度を群の全個体の平均速度に近づけようとする。
デモンストレーション
個体数
各個体が集まりながら「なんとなく」一定方向に動こうとしている。個体数が200程度と多くなると、群としての動きは鈍くなる。このとき、各個体が全く均等になるのではなく、数個程度集まって移動するさまが見られるのは興味深い。
グローバル定義部
整列の際の速度変更の度合いを指定する。この値が小さいほど素早く整列しようとする。
1 2 |
// 整列(Alignment)の速度変更度 var ALIGNMENT_RATE = 10; |
群の平均速度の算出
moveAll()
関数を変更し、群の中心の算出に続いて平均速度を求める。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
function moveAll() { // 結合(Cohesion)のための群の重心 // 整列(Alignment)のための群の平均速度 centerX = 0; centerY = 0; clusterVX = 0; clusterVY = 0; for ( var i = 0; i < creatures.length; i++ ) { centerX += creatures[i].x; centerY += creatures[i].y; clusterVX += creatures[i].vx; clusterVY += creatures[i].vy; } centerX /= creatures.length; centerY /= creatures.length; clusterVX /= creatures.length; clusterVY /= creatures.length; for ( var i = 0; i < creatures.length; i++ ) { creatures[i].move(); } } |
Creatureクラス
整列のルールを個体のmove()
メソッドに実装する。
ルール適用の順番は、結合→整列→分離。これは一般に想定される生物の行動形態、「集まろうとする→一緒の方向に向かおうとする→衝突を避ける」と符合している。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
..... this.x += this.vx * TIME_SLICE / 1000; this.y += this.vy * TIME_SLICE / 1000; // ルール:結合(Cohesion) this.vx += ( centerX - this.x ) / COHESION_RATE; this.vy += ( centerY - this.y ) / COHESION_RATE; // ルール;整列(Alignment) this.vx += ( clusterVX - this.vx ) / ALIGNMENT_RATE; this.vy += ( clusterVY - this.vy ) / ALIGNMENT_RATE; // ルール:分離(Separation) for ( var i = 0; i < creatures.length; i++ ) { if ( this != creatures[i] ) { other = creatures[i]; if ( this.distanceTo( other ) < SEPARATION_DISTANCE ) { this.vx -= other.x - this.x; this.vy -= other.y - this.y; } } } // 速さを最大値に調整 newV = Math.sqrt( this.vx * this.vx + this.vy * this.vy ); this.vx *= MAX_VELOCITY / newV; this.vy *= MAX_VELOCITY / newV ..... |
前の記事:枠組みの準備
次の記事:条件と挙動のバリエーション