【Processing】公式サイトにあったFlockingを理解する過程4

プログラミング
Photo by Sebastian Bill on Unsplash

こんにちは、コンスキです。

下の記事の続きを書いていきます。

ここまでの振り返り

ここまでの内容を振り返ります。

まず、次のような順番でスクリプトを見てきました。

  1. Flocking.pde
  2. Flock.pde
  3. Boid.pde

draw関数が設定されているFlocking.pdeから見始めました。

そこで、Flockクラスのインスタンスが作成されていたためFlock.pdeを見ました。

そこでもまた、Boidクラスのインスタンスを要素に持つArrayリストが作成されていて、今度はBoid.pdeを見始めます。

Boid.pdeの中は次の順番で見ました。

  1. Boidクラスの定義
  2. Boidクラスの定義の中にあったrunメソッドの定義
  3. さらにその中にあったflockメソッドの定義

Boid.pdeを見ると、初めの方でBoidクラスの定義がされていました。

Boidクラスの定義を確認すると、runメソッドが定義されています。

そこでrunメソッドの定義を見てみると、その中で次の4つのメソッドが実行されることになっていました。

  • flockメソッド
  • updateメソッド
  • bordersメソッド
  • renderメソッド

前回は、この中のbordersメソッドの定義を見たところで終わりました

renderメソッド

runメソッドの定義に含まれていた、4つのメソッドの最後になるrenderメソッドを見ていきます。

  • flockメソッド
  • updateメソッド
  • bordersメソッド
  • renderメソッド
void render() {
  // Draw a triangle rotated in the direction of velocity
  float theta = velocity.heading2D() + radians(90);
  // heading2D() above is now heading() but leaving old syntax until Processing.js catches up
  
  fill(200, 100);
  stroke(255);
  pushMatrix();
  translate(position.x, position.y);
  rotate(theta);
  beginShape(TRIANGLES);
  vertex(0, -r*2);
  vertex(-r, r*2);
  vertex(r, r*2);
  endShape();
  popMatrix();
}

2行目を見ると「速度の方向に回転した三角形を描く」というふうに書かれています。

最終的にボイドを描画しているのはこの部分であることがわかりました。

続いて3行目を見てみます。

float theta = velocity.heading2D() + radians(90);

「theta」という変数を定義しています。

このthetaは先ほどのコメントに書かれていた「速度の方向」を表していると考えられます。

右辺を見てみます。

「velocity.heading2D()」というメソッドがよくわからなかったので調べます。

すると、ベクトル(PVector)とX軸とのなす角を返してくれるメソッドだとわかりました。

PVector.heading2D()というふうに使うことができます。

その右にあるradians(90)は90度をラジアンにしたものを返してくれるようです。

ただ、なぜradians(90)が必要なのかは今のところわかりません。

続いて6、7行目を見てみます。

fill(200, 100);
stroke(255);

この2行はボイドの枠線塗りつぶしの色を設定している部分だとわかります。

次はこの部分です↓

pushMatrix();
translate(position.x, position.y);
rotate(theta);
beginShape(TRIANGLES);
vertex(0, -r*2);
vertex(-r, r*2);
vertex(r, r*2);
endShape();
popMatrix();

まず、translate()やrotate()に関してですが、これらのメソッドは座標ごと変形させるためのメソッドです。

例えば、translate()は次のように使います。

translate(100, 100) //座標を右に100、下に100動かす

rotate()は次のように使います。

rotate(PI) //座標を時計回りに90度動かす。引数にはラジアン角を使った角度を入れます。

そして、pushMatrixとpopMatrixという似た名前のメソッドがあります

この2つについては記事を書いていたので知っていました。

pushMatrix()保存してある座標を復活させるメソッドで、popMatrix()はその時点の座標を保存するメソッドになっています。

これらは、translate()やrotate()による座標の変形を他のボイドに影響させないために使っています。

beginShape(TRIANGLES)というメソッドは知らなかったので調べました。

このメソッドは頂点の位置を選択することで図形を描画することができるメソッドだそうです。

引数に「TRIANGLES」を渡すことで三角形を描画することができます。

公式ページによると、次のように使うことができます。

beginShape(TRIANGLES);
vertex(120, 300);
vertex(160, 120);
vertex(200, 300);
vertex(270, 80);
vertex(280, 300);
vertex(320, 80);
endShape();

この感じからすると、boid.pdeに書かれていた次のような頂点を結ぶと、

vertex(0, -r*2);
vertex(-r, r*2);
vertex(r, r*2);

次のような三角形になることがわかります。

ここでわかったことがあります。

先ほどのこの部分↓

float theta = velocity.heading2D() + radians(90);

右辺に+radias(90)があった理由です。

velocity.heading2D()は、X軸のプラスの部分とベクトルのなす角度です。

これをそのままrotete()の引数に使うとボイドの向きは次のようになります。

三角形の尖っている方向をボイドの頭だとすると、ベクトルの向きとボイドの向きが一致していないことになります。

これだと少しわかりづらいです。

そこで、「velocity.heading2D()+radias(90)」のように90度余分に回転させることで、

ボイドの向きはベクトルの向きと一致してわかりやすくなります。

ということで、render()メソッドはボイドを描画するメソッドでした。

次回に続きます

ここまで読んでくださってありがとうございます。

長くなったため、この内容は次回に続きます。

コメント

タイトルとURLをコピーしました