Boid
提供:kuhalaboWiki
(版間での差分)
(→Birdクラスのヘッダー) |
(→Birdクラスの本体) |
||
47行: | 47行: | ||
=== Birdクラスの本体 === | === Birdクラスの本体 === | ||
+ | 個体同士は、距離60未満のとき、相互作用する。 | ||
+ | |||
+ | 同じ群れの個体同士または友好的な群れの個体同士の場合 | ||
+ | #分離(Separation)距離 10 未満のとき | ||
+ | #整列(Alignment)距離 10以上 35未満のとき | ||
+ | #結合(Cohesion)距離 35以上 60未満のとき | ||
+ | |||
+ | なお、敵対する群れ同士の場合 | ||
+ | #分離(Separation)距離 60未満のとき | ||
+ | |||
;Bird.cpp | ;Bird.cpp | ||
<pre> | <pre> | ||
161行: | 171行: | ||
pos += vel; | pos += vel; | ||
+ | //壁際処理:壁にぶつかると反射する。(速度の符号反転) | ||
if( pos.x < 0 ){ | if( pos.x < 0 ){ | ||
vel.x *= -1; | vel.x *= -1; | ||
177行: | 188行: | ||
void Bird::draw() | void Bird::draw() | ||
{ | { | ||
+ | //個体の描画 | ||
ofSetColor(ourColor); | ofSetColor(ourColor); | ||
ofCircle(pos, head); | ofCircle(pos, head); |
2016年11月21日 (月) 01:56時点における版
アルゴリズム
Boidは以下の3つの規則にしたがって動く。
- 分離(Separation)
- 互いの距離が近すぎると、個体は他の個体とぶつからないように距離を広げる。
- 整列(Alignment)
- 適度な距離にいる個体同士は、同じ方向に飛ぶように速度を合わせる。
- 結合(Cohesion)
- ある程度距離が離れると、個体同士は、群れの中心方向へ向かうような速度をとる。
Birdクラスのヘッダー
- 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クラスの本体
個体同士は、距離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++; } } 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); ofCircle(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); vector<Bird> birds1; vector<Bird> birds2; vector<Bird> birds3; vector<Bird> birds4; vector<Bird> nullBirds; bool active; };
- ofApp.cpp
#include "ofApp.h" #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){ 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); ofRect(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; } }