Boid
提供:kuhalaboWiki
(版間での差分)
(ページの作成:「;Bird.h <pre> #pragma once #include "ofMain.h" class Bird { public: Bird(vector<Bird>* const, const int, ofColor, vector<Bird>* const, vector<Bird>* const, vector<...」) |
(→Boid openFrameworksのサンプル) |
||
(1人の利用者による、間の29版が非表示) | |||
1行: | 1行: | ||
+ | == openFrameworksのサンプル == | ||
+ | |||
+ | === Birdクラスのヘッダー === | ||
+ | |||
+ | * '''vec2f'''クラスは、2次元のベクトルを表す。位置、速度、加速度など、'''(x,y)'''の2次元座標で表せるデータに使用している。 | ||
+ | ** '''vec2f'''は、従来の'''ofPoint'''に相当する。 | ||
+ | ** http://openframeworks.cc/documentation/math/ofVec2f/ | ||
+ | ** set( , )は、値をセットする | ||
+ | ** getNormalize()は、正規化する(単位ベクトル化する) | ||
+ | ** distancet( , )は、2つのベクトルの距離を求める | ||
+ | ** scale( )は、ベクトルの大きさを指定した値にする | ||
+ | *クラスの動的配列として、、'''vector <クラス名>'''を使う | ||
+ | ** std::vector https://cpprefjp.github.io/reference/vector.html | ||
+ | *Birdクラスの引数 | ||
+ | *# 自分の群れ(ポインタ) vector<Bird>* const | ||
+ | *# 個体番号 const int | ||
+ | *# 個体の色 ofColor | ||
+ | *# 敵対する群れ(ポインタ) vector<Bird>* const | ||
+ | *# 友好的な群れ(ポインタ) vector<Bird>* const | ||
+ | *# 友好的な群れ2(ポインタ) vector<Bird>* const | ||
+ | |||
;Bird.h | ;Bird.h | ||
<pre> | <pre> | ||
13行: | 34行: | ||
virtual void draw(); | virtual void draw(); | ||
− | int id; | + | int id; //群れの中の個体の識別番号 |
− | float head; | + | float head; //個体の頭の半径 |
− | float tail; | + | float tail; //個体の尾の長さ |
− | ofVec2f pos; | + | ofVec2f pos; //個体の位置 |
− | ofVec2f vel; | + | ofVec2f vel; //個体の速度 |
− | ofVec2f acc; | + | ofVec2f acc; //個体の速度変化(加速度) |
− | ofColor ourColor; | + | ofColor ourColor; //個体の色 |
protected: | protected: | ||
− | vector<Bird>* pSelfGroup; | + | vector<Bird>* pSelfGroup; //自分の所属する群れ |
− | vector<Bird>* pEnemyGroup; | + | vector<Bird>* pEnemyGroup; //敵対する群れ |
− | vector<Bird>* pFriendGroup; | + | vector<Bird>* pFriendGroup; //友好的な群れ |
− | vector<Bird>* pFriendGroup2; | + | vector<Bird>* pFriendGroup2; //友好的な群れ2 |
− | ofVec2f separationVel; | + | ofVec2f separationVel; //分離 |
− | ofVec2f alignmentVel; | + | ofVec2f alignmentVel; //整列 |
− | ofVec2f cohesionVel; | + | ofVec2f cohesionVel; //結合 |
− | ofVec2f groupCenterPos; | + | ofVec2f groupCenterPos; //群れの中心位置 |
}; | }; | ||
</pre> | </pre> | ||
+ | |||
+ | === Birdクラス本体 === | ||
+ | *Birsクラスは、複数の個体からなる群れである。 | ||
+ | *個体同士は、距離60未満のとき、相互作用する。 | ||
+ | |||
+ | *同じ群れの個体同士または友好的な群れの個体同士の場合 | ||
+ | *#分離(Separation)距離 10 未満のとき | ||
+ | *#整列(Alignment)距離 10以上 35未満のとき | ||
+ | *#結合(Cohesion)距離 35以上 60未満のとき | ||
+ | |||
+ | *敵対する群れ同士の場合 | ||
+ | *#分離(Separation)距離 60未満のとき | ||
;Bird.cpp | ;Bird.cpp | ||
66行: | 99行: | ||
groupCenterPos.set(0,0); | groupCenterPos.set(0,0); | ||
− | for(int i = 0; i < pSelfGroup->size(); i++){ | + | for(int i = 0; i < pSelfGroup->size(); i++){ //自分自身の群れ内での相互作用 |
Bird& rAnother = pSelfGroup->at(i); | Bird& rAnother = pSelfGroup->at(i); | ||
− | + | if(rAnother.id != id){ //自分自身との相互作用は除く | |
− | if(rAnother.id != id){ | + | |
float dist = pos.distance( rAnother.pos ); | float dist = pos.distance( rAnother.pos ); | ||
− | + | if(dist < 10){ //分離 | |
− | if(dist < 10){ | + | |
separationVel += pos - rAnother.pos; | separationVel += pos - rAnother.pos; | ||
separationCount++; | separationCount++; | ||
} | } | ||
− | else if(dist < 35){ | + | else if(dist < 35){ //整列 |
alignmentVel += rAnother.vel.getNormalized(); | alignmentVel += rAnother.vel.getNormalized(); | ||
alignmentCount++; | alignmentCount++; | ||
} | } | ||
− | else if(dist < 60){ | + | else if(dist < 60){ //結合 |
groupCenterPos += rAnother.pos; | groupCenterPos += rAnother.pos; | ||
cohesionCount++; | cohesionCount++; | ||
87行: | 118行: | ||
} | } | ||
− | for(int i = 0; i < pFriendGroup->size(); i++){ | + | for(int i = 0; i < pFriendGroup->size(); i++){ //友好的な群れとの相互作用 |
Bird& rAnother = pFriendGroup->at(i); | Bird& rAnother = pFriendGroup->at(i); | ||
float dist = pos.distance( rAnother.pos ); | float dist = pos.distance( rAnother.pos ); | ||
105行: | 136行: | ||
} | } | ||
− | for(int i = 0; i < pFriendGroup2->size(); i++){ | + | for(int i = 0; i < pFriendGroup2->size(); i++){ //友好的な群れとの相互作用 |
Bird& rAnother = pFriendGroup2->at(i); | Bird& rAnother = pFriendGroup2->at(i); | ||
float dist = pos.distance( rAnother.pos ); | float dist = pos.distance( rAnother.pos ); | ||
123行: | 154行: | ||
} | } | ||
− | for(int i = 0; i < pEnemyGroup->size(); i++){ | + | for(int i = 0; i < pEnemyGroup->size(); i++){ //敵対的な群れとの相互作用 |
Bird& rAnother = pEnemyGroup->at(i); | Bird& rAnother = pEnemyGroup->at(i); | ||
float dist = pos.distance( rAnother.pos ); | float dist = pos.distance( rAnother.pos ); | ||
133行: | 164行: | ||
} | } | ||
+ | //速度ベクトルの正規化(大きさを1にする) | ||
separationVel /= separationCount; | separationVel /= separationCount; | ||
separationVel.normalize(); | separationVel.normalize(); | ||
− | |||
alignmentVel /= alignmentCount; | alignmentVel /= alignmentCount; | ||
alignmentVel.normalize(); | alignmentVel.normalize(); | ||
143行: | 174行: | ||
cohesionVel.normalize(); | cohesionVel.normalize(); | ||
+ | //分離、整列、結合の速度を重み付けをして速度に足しこむ | ||
vel += (separationVel*0.15) + (alignmentVel*0.035) + (cohesionVel*0.02); | vel += (separationVel*0.15) + (alignmentVel*0.035) + (cohesionVel*0.02); | ||
148行: | 180行: | ||
pos += vel; | pos += vel; | ||
+ | //壁際処理:壁にぶつかると反射する。(速度の符号反転) | ||
if( pos.x < 0 ){ | if( pos.x < 0 ){ | ||
vel.x *= -1; | vel.x *= -1; | ||
164行: | 197行: | ||
void Bird::draw() | void Bird::draw() | ||
{ | { | ||
+ | //個体の描画 | ||
ofSetColor(ourColor); | ofSetColor(ourColor); | ||
− | + | ofDrawCircle(pos, head); | |
ofLine(pos.x + vel.x * tail * 0.5, pos.y + vel.y * tail * 0.5, pos.x - vel.x * tail, pos.y - vel.y * tail); | ofLine(pos.x + vel.x * tail * 0.5, pos.y + vel.y * tail * 0.5, pos.x - vel.x * tail, pos.y - vel.y * tail); | ||
} | } | ||
</pre> | </pre> | ||
+ | |||
+ | === 全体の記述 === | ||
;ofApp.h | ;ofApp.h | ||
196行: | 232行: | ||
void gotMessage(ofMessage msg); | void gotMessage(ofMessage msg); | ||
+ | //個体の群れを4つ宣言 | ||
vector<Bird> birds1; | vector<Bird> birds1; | ||
vector<Bird> birds2; | vector<Bird> birds2; | ||
202行: | 239行: | ||
vector<Bird> nullBirds; | vector<Bird> nullBirds; | ||
− | + | bool active; //動きの制御 | |
− | + | ||
}; | }; | ||
</pre> | </pre> | ||
+ | |||
+ | 動的配列の個数(大きさは)は、例えば、 | ||
+ | <pre> | ||
+ | bird1.size() | ||
+ | </pre> | ||
+ | で参照できる。 | ||
+ | |||
+ | 新しくインスタンスを配列の末尾に追加するには、 | ||
+ | <pre> | ||
+ | birds.push_back() | ||
+ | </pre> | ||
+ | を使う。 | ||
;ofApp.cpp | ;ofApp.cpp | ||
211行: | 259行: | ||
#include "ofApp.h" | #include "ofApp.h" | ||
+ | //4つの群れの個体数 | ||
#define BOID1 100 | #define BOID1 100 | ||
#define BOID2 80 | #define BOID2 80 | ||
216行: | 265行: | ||
#define BOID4 50 | #define BOID4 50 | ||
− | #define BGCOLOR ofColor(0,0,0,32) // black | + | #define BGCOLOR ofColor(0,0,0,32) // black 背景色 |
− | #define COLOR1 ofColor(255,0,0,255) // red | + | #define COLOR1 ofColor(255,0,0,255) // red 群れの個体の色 |
#define COLOR2 ofColor(0,255,0,255) // green | #define COLOR2 ofColor(0,255,0,255) // green | ||
#define COLOR3 ofColor(0,255,255,255) //cyan | #define COLOR3 ofColor(0,255,255,255) //cyan | ||
#define COLOR4 ofColor(255,255,0,255) // yellow | #define COLOR4 ofColor(255,255,0,255) // yellow | ||
− | #define FRATE 20 | + | #define FRATE 20 //フレームレイト |
//-------------------------------------------------------------- | //-------------------------------------------------------------- | ||
236行: | 285行: | ||
active = true; | active = true; | ||
− | // self, enemy, friend1, friend2 | + | // self, enemy, friend1, friend2 群れの生成 |
birds1.reserve(BOID1); | birds1.reserve(BOID1); | ||
for(int i = 0; i < BOID1; i++){ | for(int i = 0; i < BOID1; i++){ | ||
258行: | 307行: | ||
void ofApp::update() | void ofApp::update() | ||
{ | { | ||
− | if(active){ | + | if(active){ //activeのがtrueのとき、群れの更新 |
for(int i = 0; i < birds1.size(); i++){ | for(int i = 0; i < birds1.size(); i++){ | ||
birds1[i].update(); | birds1[i].update(); | ||
278行: | 327行: | ||
{ | { | ||
ofSetColor(BGCOLOR); | ofSetColor(BGCOLOR); | ||
− | + | ofDrawRectangle(0,0, ofGetWidth(),ofGetHeight() ); | |
for(int i = 0; i < birds1.size(); i++){ | for(int i = 0; i < birds1.size(); i++){ | ||
301行: | 350行: | ||
break; | break; | ||
case 'f': | case 'f': | ||
− | ofToggleFullscreen(); | + | ofToggleFullscreen(); //フルスクリーン切り替え |
break; | break; | ||
case 's': | case 's': | ||
− | ofShowCursor(); | + | ofShowCursor(); //カーソル表示 |
break; | break; | ||
case 'h': | case 'h': | ||
− | ofHideCursor(); | + | ofHideCursor(); //カーソル非表示 |
break; | break; | ||
default: | default: | ||
314行: | 363行: | ||
} | } | ||
</pre> | </pre> | ||
+ | |||
+ | == 参考 == | ||
+ | [[ジェネラティブアート論]] | ||
+ | |||
+ | [[Category:授業]] |
2020年10月31日 (土) 00:20時点における最新版
目次 |
[編集] openFrameworksのサンプル
[編集] Birdクラスのヘッダー
- vec2fクラスは、2次元のベクトルを表す。位置、速度、加速度など、(x,y)の2次元座標で表せるデータに使用している。
- vec2fは、従来のofPointに相当する。
- http://openframeworks.cc/documentation/math/ofVec2f/
- set( , )は、値をセットする
- getNormalize()は、正規化する(単位ベクトル化する)
- distancet( , )は、2つのベクトルの距離を求める
- scale( )は、ベクトルの大きさを指定した値にする
- クラスの動的配列として、、vector <クラス名>を使う
- std::vector https://cpprefjp.github.io/reference/vector.html
- Birdクラスの引数
- 自分の群れ(ポインタ) vector<Bird>* const
- 個体番号 const int
- 個体の色 ofColor
- 敵対する群れ(ポインタ) vector<Bird>* const
- 友好的な群れ(ポインタ) vector<Bird>* const
- 友好的な群れ2(ポインタ) vector<Bird>* const
- Bird.h
#pragma once #include "ofMain.h" class Bird { public: Bird(vector<Bird>* const, const int, ofColor, vector<Bird>* const, vector<Bird>* const, vector<Bird>* const); virtual ~Bird(); virtual void update(); virtual void draw(); int id; //群れの中の個体の識別番号 float head; //個体の頭の半径 float tail; //個体の尾の長さ ofVec2f pos; //個体の位置 ofVec2f vel; //個体の速度 ofVec2f acc; //個体の速度変化(加速度) ofColor ourColor; //個体の色 protected: vector<Bird>* pSelfGroup; //自分の所属する群れ vector<Bird>* pEnemyGroup; //敵対する群れ vector<Bird>* pFriendGroup; //友好的な群れ vector<Bird>* pFriendGroup2; //友好的な群れ2 ofVec2f separationVel; //分離 ofVec2f alignmentVel; //整列 ofVec2f cohesionVel; //結合 ofVec2f groupCenterPos; //群れの中心位置 };
[編集] Birdクラス本体
- Birsクラスは、複数の個体からなる群れである。
- 個体同士は、距離60未満のとき、相互作用する。
- 同じ群れの個体同士または友好的な群れの個体同士の場合
- 分離(Separation)距離 10 未満のとき
- 整列(Alignment)距離 10以上 35未満のとき
- 結合(Cohesion)距離 35以上 60未満のとき
- 敵対する群れ同士の場合
- 分離(Separation)距離 60未満のとき
- Bird.cpp
#include "Bird.h" Bird::Bird( vector<Bird>* const _pSelfGroup, const int _id, const ofColor _ourColor, vector<Bird>* const _pEnemyGroup, vector<Bird>* const _pFriendGroup, vector<Bird>* const _pFriendGroup2 ) { pSelfGroup = _pSelfGroup; pEnemyGroup = _pEnemyGroup; pFriendGroup = _pFriendGroup; pFriendGroup2 = _pFriendGroup2; id = _id; ourColor = _ourColor; pos.set( ofRandom(0,ofGetWidth() ) , ofRandom(0,ofGetHeight() ) ); vel.set( ofRandom(-2,2), ofRandom(-2,2) ); head = 2; tail = head * 4.0; } Bird::~Bird() { } void Bird::update() { int separationCount = 0; int alignmentCount = 0; int cohesionCount = 0; separationVel.set(0,0); alignmentVel.set(0,0); cohesionVel.set(0,0); groupCenterPos.set(0,0); for(int i = 0; i < pSelfGroup->size(); i++){ //自分自身の群れ内での相互作用 Bird& rAnother = pSelfGroup->at(i); if(rAnother.id != id){ //自分自身との相互作用は除く float dist = pos.distance( rAnother.pos ); if(dist < 10){ //分離 separationVel += pos - rAnother.pos; separationCount++; } else if(dist < 35){ //整列 alignmentVel += rAnother.vel.getNormalized(); alignmentCount++; } else if(dist < 60){ //結合 groupCenterPos += rAnother.pos; cohesionCount++; } } } for(int i = 0; i < pFriendGroup->size(); i++){ //友好的な群れとの相互作用 Bird& rAnother = pFriendGroup->at(i); float dist = pos.distance( rAnother.pos ); if(dist < 10){ separationVel += pos - rAnother.pos; separationCount++; } else if(dist < 35){ alignmentVel += rAnother.vel.getNormalized(); alignmentCount++; } else if(dist < 60){ groupCenterPos += rAnother.pos; cohesionCount++; } } for(int i = 0; i < pFriendGroup2->size(); i++){ //友好的な群れとの相互作用 Bird& rAnother = pFriendGroup2->at(i); float dist = pos.distance( rAnother.pos ); if(dist < 10){ separationVel += pos - rAnother.pos; separationCount++; } else if(dist < 35){ alignmentVel += rAnother.vel.getNormalized(); alignmentCount++; } else if(dist < 60){ groupCenterPos += rAnother.pos; cohesionCount++; } } for(int i = 0; i < pEnemyGroup->size(); i++){ //敵対的な群れとの相互作用 Bird& rAnother = pEnemyGroup->at(i); float dist = pos.distance( rAnother.pos ); if(dist < 60){ separationVel += pos - rAnother.pos; separationCount++; } } //速度ベクトルの正規化(大きさを1にする) separationVel /= separationCount; separationVel.normalize(); alignmentVel /= alignmentCount; alignmentVel.normalize(); groupCenterPos /= cohesionCount; cohesionVel = groupCenterPos - pos; cohesionVel.normalize(); //分離、整列、結合の速度を重み付けをして速度に足しこむ vel += (separationVel*0.15) + (alignmentVel*0.035) + (cohesionVel*0.02); vel.scale(1.5); pos += vel; //壁際処理:壁にぶつかると反射する。(速度の符号反転) if( pos.x < 0 ){ vel.x *= -1; } else if( pos.x >= ofGetWidth() ){ vel.x *= -1; } if( pos.y < 0 ){ vel.y *= -1; } else if( pos.y >= ofGetHeight() ){ vel.y *= -1; } } void Bird::draw() { //個体の描画 ofSetColor(ourColor); ofDrawCircle(pos, head); ofLine(pos.x + vel.x * tail * 0.5, pos.y + vel.y * tail * 0.5, pos.x - vel.x * tail, pos.y - vel.y * tail); }
[編集] 全体の記述
- ofApp.h
#pragma once #include "ofMain.h" #include "ofGraphics.h" #include "Bird.h" class ofApp : 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); void dragEvent(ofDragInfo dragInfo); void gotMessage(ofMessage msg); //個体の群れを4つ宣言 vector<Bird> birds1; vector<Bird> birds2; vector<Bird> birds3; vector<Bird> birds4; vector<Bird> nullBirds; bool active; //動きの制御 };
動的配列の個数(大きさは)は、例えば、
bird1.size()
で参照できる。
新しくインスタンスを配列の末尾に追加するには、
birds.push_back()
を使う。
- ofApp.cpp
#include "ofApp.h" //4つの群れの個体数 #define BOID1 100 #define BOID2 80 #define BOID3 120 #define BOID4 50 #define BGCOLOR ofColor(0,0,0,32) // black 背景色 #define COLOR1 ofColor(255,0,0,255) // red 群れの個体の色 #define COLOR2 ofColor(0,255,0,255) // green #define COLOR3 ofColor(0,255,255,255) //cyan #define COLOR4 ofColor(255,255,0,255) // yellow #define FRATE 20 //フレームレイト //-------------------------------------------------------------- void ofApp::setup() { ofSetFrameRate(FRATE); ofEnableAlphaBlending(); ofSetBackgroundColor(0,0,0); ofSetBackgroundAuto(false); ofSetCircleResolution(64); ofHideCursor(); ofSetBackgroundColor(BGCOLOR); active = true; // self, enemy, friend1, friend2 群れの生成 birds1.reserve(BOID1); for(int i = 0; i < BOID1; i++){ birds1.push_back(*new Bird( &birds1, i, COLOR1, &birds2, &birds3, &nullBirds)); } birds2.reserve(BOID2); for(int i = 0; i < BOID2; i++){ birds2.push_back(*new Bird( &birds2, i, COLOR2, &nullBirds, &birds3, &nullBirds)); } birds3.reserve(BOID3); for(int i = 0; i < BOID3; i++){ birds3.push_back(*new Bird( &nullBirds, i, COLOR3, &nullBirds, &birds2, &nullBirds)); } birds4.reserve(BOID4); for(int i = 0; i < BOID4; i++){ birds4.push_back(*new Bird( &birds4, i, COLOR4, &birds1, &birds3, &nullBirds)); } } //-------------------------------------------------------------- void ofApp::update() { if(active){ //activeのがtrueのとき、群れの更新 for(int i = 0; i < birds1.size(); i++){ birds1[i].update(); } for(int i = 0; i < birds2.size(); i++){ birds2[i].update(); } for(int i = 0; i < birds3.size(); i++){ birds3[i].update(); } for(int i = 0; i < birds4.size(); i++){ birds4[i].update(); } } } //-------------------------------------------------------------- void ofApp::draw() { ofSetColor(BGCOLOR); ofDrawRectangle(0,0, ofGetWidth(),ofGetHeight() ); for(int i = 0; i < birds1.size(); i++){ birds1[i].draw(); } for(int i = 0; i < birds2.size(); i++){ birds2[i].draw(); } for(int i = 0; i < birds3.size(); i++){ birds3[i].draw(); } for(int i = 0; i < birds4.size(); i++){ birds4[i].draw(); } } //-------------------------------------------------------------- void ofApp::keyPressed(int key){ switch (key){ case ' ': active = !active; break; case 'f': ofToggleFullscreen(); //フルスクリーン切り替え break; case 's': ofShowCursor(); //カーソル表示 break; case 'h': ofHideCursor(); //カーソル非表示 break; default: break; } }