// 識別子が長すぎるワーニングを無効 #pragma warning (disable : 4786) #include "ats_boid.h" #include "ats_BoidGroup.h" #include #include #include using namespace std; using namespace ats; // Boid クラスメンバ --------------------------------------------------------------------- //double g_one = 1.5; #define g_one 1.5 double Boid::m_box_right = g_one; double Boid::m_box_left = -g_one; double Boid::m_box_top = g_one; double Boid::m_box_bottom = -g_one; double Boid::m_box_front = g_one; double Boid::m_box_back = -g_one; double Boid::m_box_max = g_one; double Boid::m_box_min = -g_one; // コンストラクタ・デストラクタ ---------------------------------------------------------- inline double drand(int max, double dmax){ return static_cast(rand() % max) / 100 - dmax; }; Boid::Boid(int max, int max2, int tail_num, double speed) : m_parent(0), m_tail_num(tail_num), m_tail(m_tail_num), m_tail_itr(m_tail.begin()), m_speed((10 - rand() % 4) * 0.1 * speed) // 10〜7 { // 位置と速度の最大値 double dmax = max; double dmax2 = max2; dmax /= 200; dmax2 /= 200; m_center.SetXYZ(drand(max,dmax), drand(max,dmax), drand(max,dmax)); m_muki.SetXYZ (drand(max,dmax), drand(max,dmax), drand(max,dmax)); } // コピーコンストラクタ ----------------------------------------------------------------- Boid::Boid(const Boid& boid) { } Boid::~Boid() { } // UpdateTimeの実装サンプル void Boid::UpdateTime(double time) { bool crush_flag = false; // そのまま //if(m_parent != 0 && m_near != 0){ // Nearはしょる if(m_parent != 0){ // 次の方向 = 中央への方向 + 現在の方向 + 群れの方向 // 向き = 群への協調 + 自分の慣性 + ニアミスを避ける。 //Point3D go_parent(m_parent->Center() - m_center); //Point3D not_crush(m_center - m_near->m_center); // 中心へ + 群への協調 + 慣性 + 衝突回避 // OK m_muki = ((m_parent->Center()-m_center)*0.03 + m_parent->Muki()*0.03 + m_muki*0.95 + m_near->GetMuki()*0.01); // Nearをはしょってないやつ //m_muki = ((m_parent->Center()-m_center)*0.23 + m_parent->Muki()*0.023 + m_muki*1.5 + m_near->GetMuki()*0.01); // Nearをはしょったやつ m_muki = ((m_parent->Center()-m_center) * 0.05 + m_parent->Muki() * 0.08 + m_muki * 1.1); m_muki.Normalize() *= m_speed; // ボックスの外側にあって if(m_center.X() > m_box_max || m_center.X() < m_box_min || m_center.Y() > m_box_max || m_center.Y() < m_box_min || m_center.Z() > m_box_max || m_center.Z() < m_box_min) { m_center *= 0.98; // ちょっと中心に寄せてやってから m_muki *= -0.5; // 方向反転 } else { m_muki += (Point(rand()%10-5,rand()%10-5,rand()%10-5)).Normalize()*0.057; //m_muki.Normalize(); } // 前の位置を保存 *m_tail_itr = m_center; if(m_tail_itr == m_tail.begin()){ // イテレータを逆向きに移動 m_tail_itr = m_tail.end(); m_tail_itr--; } else { m_tail_itr--; } m_center += m_muki * 0.03; } } void Boid::SetNear(Boid* a) { m_near = a; } Boid* Boid::GetNear() const { return m_near; } bool Boid::IsNear() const { if(m_near == 0) return false; else return true; } void Boid::SetParent(BoidGroup* a) { m_parent = a; } BoidGroup* Boid::GetParent() const { return m_parent; } bool Boid::IsParent() const { if(m_parent == 0) return false; else return true; } Point3D Boid::GetCenter() const { return m_center; } void Boid::SetCenter(const Point3D& a) { m_center = a; } Point3D Boid::GetMuki() const { return m_muki; } void Boid::SetMuki(const Point3D& a) { m_muki = a; } void Boid::SetTailNumber(const int a) { m_tail_num = a; m_tail.resize(a); } int Boid::GetTailNumber() const { return m_tail_num; } void Boid::SetSpeed(const double a) { m_speed = a; } double Boid::GetSpeed() const { return m_speed; } Point3D Boid::GetTailPoint(int a) const // 頭のほうから { // イテレータは途中から始まるため、一周分だけ余裕を持たせる if(a >= m_tail_num){ a -= m_tail_num; } return *(m_tail_itr + a); }