群衆をシミュレーションするBoids理論というものがあります。生物っぽい動きが作れるので楽しいのですが、何しろ実装が大変。そこで、openFrameworksでAddonないかなーって探したらありました。しかも2つも。今回はこっちofxBoidsを使いたいと思います。

まず、testApp.hFlock2dのオブジェクトを宣言します。

[code lang=cpp]
class testApp : public ofBaseApp{

public:
void setup();
void update();
void draw();

void keyPressed (int key);
void keyReleased(int key);
void mouseMoved(int x, int y );
void mouseDragged(int x, int y, int button);
void mousePressed(int x, int y, int button);
void mouseReleased(int x, int y, int button);
void windowResized(int w, int h);

Flock2d flock;
};
[/code]

んで、flockの設定もろもろをsetup()内に。

[code lang=cpp]
void testApp::setup(){
ofSetFrameRate(60);
ofBackground(0);

// flockの設定。第一引数は個体の数。
flock.setup(50, ofGetWidth()/2, ofGetHeight()/2);
// 壁を設定。
flock.setBounds(0, 0, ofGetWidth(), ofGetHeight());

flock.setMaxSpeed(3); //最大速度
flock.setMaxTurn(0.1); //最大回転速度
flock.setAlign(1); // 整列の力
flock.setCohesion(2); // 結合の力
flock.setSeparate(1.5); // 分離の力

//中心に向かう力を設定。
//第三引数は力の強さ、第四引数は引きよせ始める距離
//第三引数を負にすると逃げる。
flock.addAttractionPoint(ofGetWidth()/2, ofGetHeight()/2,50,300);
}
[/code]

んでupdate()draw()は次のようにします。

[code lang=cpp]
void testApp::update(){
flock.update();
}

void testApp::draw(){
for (int i=0; i<flock.size(); i++) {
Boid2d * b = flock.get(i);
ofSetColor(255, 0, 0);
ofPushMatrix();
ofTranslate(b->x, b->y);
ofRotate(atan2(b->vy, b->vx)*RAD_TO_DEG);
ofBeginShape();
ofVertex(0, 2);
ofVertex(3, 0);
ofVertex(0, -2);
ofVertex(-24, 0);
ofEndShape();
ofPopMatrix();
}
}
[/code]

あとはこのdraw()の中でb->x, b->y, b->vx, b->vyを使えば、個体の場所と速度が取れます。なお、個体を増やすときは、flock.add(int x, int y)を使い、減らすときはflock.remove(int id)を使います。

これとOpenCVを使って、手で丸を作ると、魚が飛び出てくるプログラムを作りました。生体シミュレーションは面白いので是非一度ためしてみては?

手で丸を作ると魚が飛び出てくる