Boid
提供:kuhalaboWiki
(版間での差分)
(→Birdクラスの本体) |
(→Birdクラスの本体) |
||
| 46行: | 46行: | ||
</pre> | </pre> | ||
| − | === | + | === Birdクラス本体 === |
個体同士は、距離60未満のとき、相互作用する。 | 個体同士は、距離60未満のとき、相互作用する。 | ||
| 95行: | 95行: | ||
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++; | ||
| 156行: | 156行: | ||
} | } | ||
| + | //速度ベクトルの正規化(大きさを1にする) | ||
separationVel /= separationCount; | separationVel /= separationCount; | ||
separationVel.normalize(); | separationVel.normalize(); | ||
| − | |||
alignmentVel /= alignmentCount; | alignmentVel /= alignmentCount; | ||
alignmentVel.normalize(); | alignmentVel.normalize(); | ||
| 166行: | 166行: | ||
cohesionVel.normalize(); | cohesionVel.normalize(); | ||
| + | //分離、整列、結合の速度を比例配分して速度に足しこむ | ||
vel += (separationVel*0.15) + (alignmentVel*0.035) + (cohesionVel*0.02); | vel += (separationVel*0.15) + (alignmentVel*0.035) + (cohesionVel*0.02); | ||
| 194行: | 195行: | ||
} | } | ||
</pre> | </pre> | ||
| + | |||
| + | === 全体の記述 === | ||
;ofApp.h | ;ofApp.h | ||
| 221行: | 224行: | ||
void gotMessage(ofMessage msg); | void gotMessage(ofMessage msg); | ||
| + | //個体の群れを4つ宣言 | ||
vector<Bird> birds1; | vector<Bird> birds1; | ||
vector<Bird> birds2; | vector<Bird> birds2; | ||
| 227行: | 231行: | ||
vector<Bird> nullBirds; | vector<Bird> nullBirds; | ||
| − | + | bool active; //動きの制御 | |
| − | + | ||
}; | }; | ||
</pre> | </pre> | ||
| 236行: | 239行: | ||
#include "ofApp.h" | #include "ofApp.h" | ||
| + | //4つの群れの個体数 | ||
#define BOID1 100 | #define BOID1 100 | ||
#define BOID2 80 | #define BOID2 80 | ||
| 241行: | 245行: | ||
#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 //フレームレイト |
//-------------------------------------------------------------- | //-------------------------------------------------------------- | ||
| 329行: | 333行: | ||
break; | break; | ||
case 's': | case 's': | ||
| − | ofShowCursor(); | + | ofShowCursor(); //カーソル表示 |
break; | break; | ||
case 'h': | case 'h': | ||
| − | ofHideCursor(); | + | ofHideCursor(); //カーソル非表示 |
break; | break; | ||
default: | default: | ||
2016年11月21日 (月) 02:11時点における版
目次 |
アルゴリズム
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++;
}
}
//速度ベクトルの正規化(大きさを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);
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);
//個体の群れを4つ宣言
vector<Bird> birds1;
vector<Bird> birds2;
vector<Bird> birds3;
vector<Bird> birds4;
vector<Bird> nullBirds;
bool active; //動きの制御
};
- 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){
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;
}
}