Panda3D
|
00001 //////////////////////////////////////////////////////////////////////// 00002 // Filename : aiBehaviors.cxx 00003 // Created by : Deepak, John, Navin 00004 // Date : 8 Sep 09 00005 //////////////////////////////////////////////////////////////////// 00006 // 00007 // PANDA 3D SOFTWARE 00008 // Copyright (c) Carnegie Mellon University. All rights reserved. 00009 // 00010 // All use of this software is subject to the terms of the revised BSD 00011 // license. You should have received a copy of this license along 00012 // with this source code in a file named "LICENSE." 00013 // 00014 //////////////////////////////////////////////////////////////////// 00015 00016 #include "aiBehaviors.h" 00017 00018 static const float _PI = 3.14; 00019 00020 AIBehaviors::AIBehaviors() { 00021 _steering_force = LVecBase3f(0.0, 0.0, 0.0); 00022 _behaviors_flags = _behaviors_flags & _none; 00023 _previous_conflict = false; 00024 _conflict = false; 00025 00026 _seek_obj = NULL; 00027 _flee_obj = NULL; 00028 _pursue_obj = NULL; 00029 _evade_obj = NULL; 00030 _arrival_obj = NULL; 00031 _wander_obj = NULL; 00032 _flock_group = NULL; 00033 _path_follow_obj = NULL; 00034 _path_find_obj = NULL; 00035 _obstacle_avoidance_obj = NULL; 00036 00037 turn_off("seek"); 00038 turn_off("flee"); 00039 turn_off("pursue"); 00040 turn_off("evade"); 00041 turn_off("arrival"); 00042 turn_off("flock"); 00043 turn_off("wander"); 00044 turn_off("obstacle_avoidance"); 00045 } 00046 00047 AIBehaviors::~AIBehaviors() { 00048 00049 } 00050 00051 ///////////////////////////////////////////////////////////////////////////////// 00052 // 00053 // Function : is_conflict 00054 // Description : Checks for conflict between steering forces. 00055 // If there is a conflict it returns 'true' and sets _conflict to 'true'. 00056 // If there is no conflict it returns 'false' and sets _conflict to 'false'. 00057 00058 ///////////////////////////////////////////////////////////////////////////////// 00059 00060 bool AIBehaviors::is_conflict() { 00061 int value = int(is_on(_seek)) + int(is_on(_flee)) + int(is_on(_pursue)) + int(is_on(_evade)) + int(is_on(_wander)) + int(is_on(_flock))+ int(is_on(_obstacle_avoidance)); 00062 00063 if(value > 1) { 00064 if(_previous_conflict == false) { 00065 if(is_on(_seek)) { 00066 _seek_force *= _seek_obj->_seek_weight; 00067 } 00068 00069 if(is_on(_flee)) { 00070 LVecBase3f dirn = _flee_force; 00071 dirn.normalize(); 00072 _flee_force = _steering_force.length() * dirn * _flee_obj->_flee_weight; 00073 } 00074 00075 if(is_on(_pursue)) { 00076 _pursue_force *= _pursue_obj->_pursue_weight; 00077 } 00078 00079 if(is_on(_evade)) { 00080 LVecBase3f dirn = _evade_force; 00081 dirn.normalize(); 00082 _evade_force = _steering_force.length() * dirn * _evade_obj->_evade_weight; 00083 } 00084 00085 if(is_on(_flock)) { 00086 _flock_force *= _flock_weight; 00087 } 00088 00089 if(is_on(_wander)) { 00090 _wander_force *= _wander_obj->_wander_weight; 00091 } 00092 00093 _previous_conflict = true; 00094 } 00095 00096 _conflict = true; 00097 return true; 00098 } 00099 00100 _conflict = false; 00101 _previous_conflict = false; 00102 return false; 00103 } 00104 00105 ///////////////////////////////////////////////////////////////////////////////////////////////////// 00106 // 00107 // Function : accumulate_force 00108 // Description : This function updates the individual steering forces for each of the ai characters. 00109 // These accumulated forces are eventually what comprise the resultant 00110 // steering force of the character. 00111 00112 ///////////////////////////////////////////////////////////////////////////////////////////////////// 00113 00114 void AIBehaviors::accumulate_force(string force_type, LVecBase3f force) { 00115 00116 LVecBase3f old_force; 00117 00118 if(force_type == "seek") { 00119 old_force = _seek_force; 00120 _seek_force = old_force + force; 00121 } 00122 00123 if(force_type == "flee") { 00124 old_force = _flee_force; 00125 _flee_force = old_force + force; 00126 } 00127 00128 if(force_type == "pursue") { 00129 old_force = _pursue_force; 00130 double new_force = old_force.length() + force.length(); 00131 _pursue_force = new_force * _pursue_obj->_pursue_direction; 00132 } 00133 00134 if(force_type == "evade") { 00135 old_force = _evade_force; 00136 double new_force = old_force.length() + force.length(); 00137 force.normalize(); 00138 _evade_force = new_force * force; 00139 } 00140 00141 if(force_type == "arrival") { 00142 _arrival_force = force; 00143 } 00144 00145 if(force_type == "flock") { 00146 old_force = _flock_force; 00147 _flock_force = old_force + force; 00148 } 00149 00150 if(force_type == "wander") { 00151 old_force = _wander_force; 00152 _wander_force = old_force + force; 00153 } 00154 00155 if(force_type == "obstacle_avoidance") { 00156 old_force = _obstacle_avoidance_force; 00157 _obstacle_avoidance_force = old_force +force; 00158 } 00159 00160 } 00161 00162 ////////////////////////////////////////////////////////////////////////////////////////////// 00163 // 00164 // Function : calculate_prioritized 00165 // Description : This function updates the main steering force for the ai character using 00166 // the accumulate function and checks for max force and arrival force. 00167 // It finally returns this steering force which is accessed by the update 00168 // function in the AICharacter class. 00169 00170 ////////////////////////////////////////////////////////////////////////////////////////////// 00171 00172 LVecBase3f AIBehaviors::calculate_prioritized() { 00173 LVecBase3f force; 00174 00175 if(is_on(_seek)) { 00176 if(_conflict) { 00177 force = _seek_obj->do_seek() * _seek_obj->_seek_weight; 00178 } 00179 else { 00180 force = _seek_obj->do_seek(); 00181 } 00182 accumulate_force("seek",force); 00183 } 00184 00185 if(is_on(_flee_activate)) { 00186 for(_flee_itr = _flee_list.begin(); _flee_itr != _flee_list.end(); _flee_itr++) { 00187 _flee_itr->flee_activate(); 00188 } 00189 } 00190 00191 if(is_on(_flee)) { 00192 for(_flee_itr = _flee_list.begin(); _flee_itr != _flee_list.end(); _flee_itr++) { 00193 if(_flee_itr->_flee_activate_done) { 00194 if(_conflict) { 00195 force = _flee_itr->do_flee() * _flee_itr->_flee_weight; 00196 } 00197 else { 00198 force = _flee_itr->do_flee(); 00199 } 00200 accumulate_force("flee",force); 00201 } 00202 } 00203 } 00204 00205 if(is_on(_pursue)) { 00206 if(_conflict) { 00207 force = _pursue_obj->do_pursue() * _pursue_obj->_pursue_weight; 00208 } 00209 else { 00210 force = _pursue_obj->do_pursue(); 00211 } 00212 accumulate_force("pursue",force); 00213 } 00214 00215 if(is_on(_evade_activate)) { 00216 for(_evade_itr = _evade_list.begin(); _evade_itr != _evade_list.end(); _evade_itr++) { 00217 _evade_itr->evade_activate(); 00218 } 00219 } 00220 00221 if(is_on(_evade)) { 00222 for(_evade_itr = _evade_list.begin(); _evade_itr != _evade_list.end(); _evade_itr++) { 00223 if(_evade_itr->_evade_activate_done) { 00224 if(_conflict) { 00225 force = (_evade_itr->do_evade()) * (_evade_itr->_evade_weight); 00226 } 00227 else { 00228 force = _evade_itr->do_evade(); 00229 } 00230 accumulate_force("evade",force); 00231 } 00232 } 00233 } 00234 00235 if(is_on(_arrival_activate)) { 00236 _arrival_obj->arrival_activate(); 00237 } 00238 00239 if(is_on(_arrival)) { 00240 force = _arrival_obj->do_arrival(); 00241 accumulate_force("arrival",force); 00242 } 00243 00244 if(is_on(_flock_activate)) { 00245 flock_activate(); 00246 } 00247 00248 if(is_on(_flock)) { 00249 if(_conflict) { 00250 force = do_flock() * _flock_weight; 00251 } 00252 else { 00253 force = do_flock(); 00254 } 00255 accumulate_force("flock",force); 00256 } 00257 00258 if(is_on(_wander)) { 00259 if(_conflict) { 00260 force = _wander_obj->do_wander() * _wander_obj->_wander_weight; 00261 } 00262 else { 00263 force = _wander_obj->do_wander(); 00264 } 00265 accumulate_force("wander", force); 00266 } 00267 00268 if(is_on(_obstacle_avoidance_activate)) { 00269 _obstacle_avoidance_obj->obstacle_avoidance_activate(); 00270 } 00271 00272 if(is_on(_obstacle_avoidance)) { 00273 if(_conflict) { 00274 force = _obstacle_avoidance_obj->do_obstacle_avoidance(); 00275 } 00276 else { 00277 force = _obstacle_avoidance_obj->do_obstacle_avoidance(); 00278 } 00279 accumulate_force("obstacle_avoidance", force); 00280 } 00281 00282 if(_path_follow_obj!=NULL) { 00283 if(_path_follow_obj->_start) { 00284 _path_follow_obj->do_follow(); 00285 } 00286 } 00287 00288 is_conflict(); 00289 00290 _steering_force += _seek_force * int(is_on(_seek)) + _flee_force * int(is_on(_flee)) + 00291 _pursue_force * int(is_on(_pursue)) + _evade_force * int(is_on(_evade)) + 00292 _flock_force * int(is_on(_flock)) + _wander_force * int(is_on(_wander)) + 00293 _obstacle_avoidance_force * int(is_on(_obstacle_avoidance)); 00294 00295 if(_steering_force.length() > _ai_char->get_max_force()) { 00296 _steering_force.normalize(); 00297 _steering_force = _steering_force * _ai_char->get_max_force(); 00298 } 00299 00300 if(is_on(_arrival)) { 00301 if(_seek_obj != NULL) { 00302 LVecBase3f dirn = _steering_force; 00303 dirn.normalize(); 00304 _steering_force = ((_steering_force.length() - _arrival_force.length()) * dirn); 00305 } 00306 00307 if(_pursue_obj != NULL) { 00308 LVecBase3f dirn = _steering_force; 00309 dirn.normalize(); 00310 _steering_force = ((_steering_force.length() - _arrival_force.length()) * _arrival_obj->_arrival_direction); 00311 } 00312 } 00313 return _steering_force; 00314 } 00315 00316 ///////////////////////////////////////////////////////////////////////////////// 00317 // 00318 // Function : remove_ai 00319 // Description : This function removes individual or all the AIs. 00320 00321 ///////////////////////////////////////////////////////////////////////////////// 00322 00323 //add for path follow 00324 void AIBehaviors::remove_ai(string ai_type) { 00325 switch(char_to_int(ai_type)) { 00326 case 0: { 00327 remove_ai("seek"); 00328 remove_ai("flee"); 00329 remove_ai("pursue"); 00330 remove_ai("evade"); 00331 remove_ai("arrival"); 00332 remove_ai("flock"); 00333 remove_ai("wander"); 00334 remove_ai("obstacle_avoidance"); 00335 remove_ai("pathfollow"); 00336 break; 00337 } 00338 00339 case 1: { 00340 if(_seek_obj != NULL) { 00341 turn_off("seek"); 00342 delete _seek_obj; 00343 _seek_obj = NULL; 00344 } 00345 break; 00346 } 00347 00348 case 2: { 00349 while (!_flee_list.empty()) { 00350 turn_off("flee"); 00351 turn_off("flee_activate"); 00352 _flee_list.pop_front(); 00353 } 00354 break; 00355 } 00356 00357 case 3: { 00358 if(_pursue_obj != NULL) { 00359 turn_off("pursue"); 00360 delete _pursue_obj; 00361 _pursue_obj = NULL; 00362 } 00363 break; 00364 } 00365 00366 case 4: { 00367 while (!_evade_list.empty()) { 00368 turn_off("evade"); 00369 turn_off("evade_activate"); 00370 _evade_list.pop_front(); 00371 } 00372 break; 00373 } 00374 00375 case 5: { 00376 if(_arrival_obj != NULL) { 00377 turn_off("arrival"); 00378 turn_off("arrival_activate"); 00379 delete _arrival_obj; 00380 _arrival_obj = NULL; 00381 } 00382 break; 00383 } 00384 00385 case 6: { 00386 if(_flock_group != NULL) { 00387 turn_off("flock"); 00388 turn_off("flock_activate"); 00389 _flock_group = NULL; 00390 } 00391 break; 00392 } 00393 00394 case 7: { 00395 if(_wander_obj != NULL) { 00396 turn_off("wander"); 00397 delete _wander_obj; 00398 _wander_obj = NULL; 00399 } 00400 break; 00401 } 00402 00403 case 8: { 00404 if(_obstacle_avoidance_obj !=NULL) { 00405 turn_off("obstacle_avoidance"); 00406 delete _obstacle_avoidance_obj; 00407 _obstacle_avoidance_obj = NULL; 00408 } 00409 break; 00410 } 00411 00412 case 9: { 00413 if(_pursue_obj != NULL && _path_follow_obj != NULL) { 00414 turn_off("pursue"); 00415 delete _pursue_obj; 00416 _pursue_obj = NULL; 00417 delete _path_follow_obj; 00418 _path_follow_obj = NULL; 00419 } 00420 break; 00421 } 00422 case 16: { 00423 if(_pursue_obj != NULL && _path_follow_obj != NULL) { 00424 turn_off("pursue"); 00425 delete _pursue_obj; 00426 _pursue_obj = NULL; 00427 delete _path_follow_obj; 00428 _path_follow_obj = NULL; 00429 } 00430 break; 00431 } 00432 default: 00433 cout<<"Invalid option!"<<endl; 00434 } 00435 } 00436 00437 ///////////////////////////////////////////////////////////////////////////////// 00438 // 00439 // Function : pause_ai 00440 // Description : This function pauses individual or all the AIs. 00441 00442 ///////////////////////////////////////////////////////////////////////////////// 00443 00444 //add for path follow 00445 void AIBehaviors::pause_ai(string ai_type) { 00446 switch(char_to_int(ai_type)) { 00447 case 0: { 00448 pause_ai("seek"); 00449 pause_ai("flee"); 00450 pause_ai("pursue"); 00451 pause_ai("evade"); 00452 pause_ai("arrival"); 00453 pause_ai("flock"); 00454 pause_ai("wander"); 00455 pause_ai("obstacle_avoidance"); 00456 pause_ai("pathfollow"); 00457 break; 00458 } 00459 00460 case 1: { 00461 if(_seek_obj != NULL) { 00462 turn_off("seek"); 00463 } 00464 break; 00465 } 00466 00467 case 2: { 00468 for(_flee_itr = _flee_list.begin(); _flee_itr != _flee_list.end(); _flee_itr++) { 00469 turn_off("flee"); 00470 turn_off("flee_activate"); 00471 } 00472 break; 00473 } 00474 00475 case 3: { 00476 if(_pursue_obj != NULL) { 00477 turn_off("pursue"); 00478 } 00479 break; 00480 } 00481 00482 case 4: { 00483 for(_evade_itr = _evade_list.begin(); _evade_itr != _evade_list.end(); _evade_itr++) { 00484 turn_off("evade"); 00485 turn_off("evade_activate"); 00486 } 00487 break; 00488 } 00489 00490 case 5: { 00491 if(_arrival_obj != NULL) { 00492 turn_off("arrival"); 00493 turn_off("arrival_activate"); 00494 } 00495 break; 00496 } 00497 00498 case 6: { 00499 if(_flock_group != NULL) { 00500 turn_off("flock"); 00501 turn_off("flock_activate"); 00502 } 00503 break; 00504 } 00505 00506 case 7: { 00507 if(_wander_obj != NULL) { 00508 turn_off("wander"); 00509 } 00510 break; 00511 } 00512 00513 case 8: { 00514 if(_obstacle_avoidance != NULL) { 00515 turn_off("obstacle_avoidance"); 00516 turn_off("obstacle_avoidance_activate"); 00517 } 00518 break; 00519 } 00520 00521 case 9: { 00522 if(_pursue_obj != NULL && _path_follow_obj != NULL) { 00523 turn_off("pursue"); 00524 _path_follow_obj->_start = false; 00525 } 00526 break; 00527 } 00528 case 16: { 00529 if(_pursue_obj != NULL && _path_follow_obj != NULL) { 00530 turn_off("pursue"); 00531 _path_follow_obj->_start = false; 00532 } 00533 break; 00534 } 00535 default: 00536 cout<<"Invalid option!"<<endl; 00537 } 00538 } 00539 00540 ///////////////////////////////////////////////////////////////////////////////// 00541 // 00542 // Function : resume_ai 00543 // Description : This function resumes individual or all the AIs 00544 00545 ///////////////////////////////////////////////////////////////////////////////// 00546 00547 void AIBehaviors::resume_ai(string ai_type) { 00548 switch(char_to_int(ai_type)) { 00549 case 0: { 00550 resume_ai("seek"); 00551 resume_ai("flee"); 00552 resume_ai("pursue"); 00553 resume_ai("evade"); 00554 resume_ai("arrival"); 00555 resume_ai("flock"); 00556 resume_ai("wander"); 00557 resume_ai("obstacle_avoidance"); 00558 resume_ai("pathfollow"); 00559 break; 00560 } 00561 00562 case 1: { 00563 if(_seek_obj != NULL) { 00564 turn_on("seek"); 00565 } 00566 break; 00567 } 00568 00569 case 2: { 00570 for(_flee_itr = _flee_list.begin(); _flee_itr != _flee_list.end(); _flee_itr++) { 00571 turn_on("flee"); 00572 } 00573 break; 00574 } 00575 00576 case 3: { 00577 if(_pursue_obj != NULL) { 00578 turn_on("pursue"); 00579 } 00580 break; 00581 } 00582 00583 case 4: { 00584 for(_evade_itr = _evade_list.begin(); _evade_itr != _evade_list.end(); _evade_itr++) { 00585 turn_on("evade"); 00586 } 00587 break; 00588 } 00589 00590 case 5: { 00591 if(_arrival_obj != NULL) { 00592 turn_on("arrival"); 00593 } 00594 break; 00595 } 00596 00597 case 6: { 00598 if(_flock_group != NULL) { 00599 turn_on("flock"); 00600 } 00601 break; 00602 } 00603 00604 case 7: { 00605 if(_wander_obj != NULL) { 00606 turn_on("wander"); 00607 } 00608 break; 00609 } 00610 00611 case 8: { 00612 if(_obstacle_avoidance_obj != NULL) { 00613 turn_on("obstacle_avoidance"); 00614 } 00615 break; 00616 } 00617 00618 case 9: { 00619 if(_pursue_obj != NULL && _path_follow_obj != NULL) { 00620 turn_on("pursue"); 00621 _path_follow_obj->_start = true; 00622 } 00623 break; 00624 } 00625 case 16: { 00626 if(_pursue_obj != NULL && _path_follow_obj != NULL) { 00627 turn_off("pursue"); 00628 _path_follow_obj->_start = false; 00629 } 00630 break; 00631 } 00632 default: 00633 cout<<"Invalid option!"<<endl; 00634 } 00635 } 00636 00637 ///////////////////////////////////////////////////////////////////////////////// 00638 // 00639 // Function : seek 00640 // Description : This function activates seek and makes an object of the Seek class. 00641 // This is the function we want the user to call for seek to be done. 00642 // This function is overloaded to accept a NodePath or an LVecBase3f. 00643 00644 ///////////////////////////////////////////////////////////////////////////////// 00645 00646 void AIBehaviors::seek(NodePath target_object, float seek_wt) { 00647 _seek_obj = new Seek(_ai_char, target_object, seek_wt); 00648 turn_on("seek"); 00649 } 00650 00651 void AIBehaviors::seek(LVecBase3f pos, float seek_wt) { 00652 _seek_obj = new Seek(_ai_char, pos, seek_wt); 00653 turn_on("seek"); 00654 } 00655 00656 ////////////////////////////////////////////////////////////////////////////////////////////////// 00657 // 00658 // Function : flee 00659 // Description : This function activates flee_activate and creates an object of the Flee class. 00660 // This function is overloaded to accept a NodePath or an LVecBase3f. 00661 00662 ////////////////////////////////////////////////////////////////////////////////////////////////// 00663 00664 void AIBehaviors::flee(NodePath target_object, double panic_distance, double relax_distance, float flee_wt) { 00665 _flee_obj = new Flee(_ai_char, target_object, panic_distance, relax_distance, flee_wt); 00666 _flee_list.insert(_flee_list.end(), *_flee_obj); 00667 00668 turn_on("flee_activate"); 00669 } 00670 00671 void AIBehaviors::flee(LVecBase3f pos, double panic_distance, double relax_distance, float flee_wt) { 00672 _flee_obj = new Flee(_ai_char, pos, panic_distance, relax_distance, flee_wt); 00673 _flee_list.insert(_flee_list.end(), *_flee_obj); 00674 00675 turn_on("flee_activate"); 00676 } 00677 00678 ///////////////////////////////////////////////////////////////////////////////// 00679 // 00680 // Function : pursue 00681 // Description : This function activates pursue. 00682 // This is the function we want the user to call for pursue to be done. 00683 00684 ///////////////////////////////////////////////////////////////////////////////// 00685 00686 void AIBehaviors::pursue(NodePath target_object, float pursue_wt) { 00687 _pursue_obj = new Pursue(_ai_char, target_object, pursue_wt); 00688 00689 turn_on("pursue"); 00690 } 00691 00692 ///////////////////////////////////////////////////////////////////////////////// 00693 // 00694 // Function : evade 00695 // Description : This function activates evade_activate. 00696 00697 ///////////////////////////////////////////////////////////////////////////////// 00698 00699 void AIBehaviors::evade(NodePath target_object, double panic_distance, double relax_distance, float evade_wt) { 00700 _evade_obj = new Evade(_ai_char, target_object, panic_distance, relax_distance, evade_wt); 00701 _evade_list.insert(_evade_list.end(), *_evade_obj); 00702 00703 turn_on("evade_activate"); 00704 } 00705 00706 ///////////////////////////////////////////////////////////////////////////////// 00707 // 00708 // Function : arrival 00709 // Description : This function activates arrival. 00710 // This is the function we want the user to call for arrival to be done. 00711 00712 ///////////////////////////////////////////////////////////////////////////////// 00713 00714 void AIBehaviors::arrival(double distance) { 00715 if(_pursue_obj) { 00716 _arrival_obj = new Arrival(_ai_char, distance); 00717 _arrival_obj->_arrival_type = true; 00718 turn_on("arrival_activate"); 00719 } 00720 else if(_seek_obj) { 00721 _arrival_obj = new Arrival(_ai_char, distance); 00722 _arrival_obj->_arrival_type = false; 00723 turn_on("arrival_activate"); 00724 } 00725 else { 00726 cout<<"Note: A Seek or Pursue behavior is required to use Arrival behavior."<<endl; 00727 } 00728 } 00729 00730 ///////////////////////////////////////////////////////////////////////////////// 00731 // 00732 // Function : flock 00733 // Description : This function activates flock. 00734 // This is the function we want the user to call for flock to be done. 00735 00736 ///////////////////////////////////////////////////////////////////////////////// 00737 00738 void AIBehaviors::flock(float flock_wt) { 00739 _flock_weight = flock_wt; 00740 00741 _flock_done = false; 00742 turn_on("flock_activate"); 00743 } 00744 00745 ///////////////////////////////////////////////////////////////////////////////// 00746 // 00747 // Function : flock_activate 00748 // Description : This function checks whether any other behavior exists to work with flock. 00749 // When this is true, it calls the do_flock function. 00750 00751 ///////////////////////////////////////////////////////////////////////////////// 00752 00753 void AIBehaviors::flock_activate() { 00754 if(is_on(_seek) || is_on(_flee) || is_on(_pursue) || is_on(_evade) || is_on(_wander)) { 00755 turn_off("flock_activate"); 00756 turn_on("flock"); 00757 } 00758 } 00759 00760 ///////////////////////////////////////////////////////////////////////////////// 00761 // 00762 // Function : do_flock 00763 // Description : This function contains the logic for flocking behavior. This is 00764 // an emergent behavior and is obtained by combining three other 00765 // behaviors which are separation, cohesion and alignment based on 00766 // Craig Reynold's algorithm. Also, this behavior does not work by 00767 // itself. It works only when combined with other steering behaviors 00768 // such as wander, pursue, evade, seek and flee. 00769 00770 ///////////////////////////////////////////////////////////////////////////////// 00771 00772 LVecBase3f AIBehaviors::do_flock() { 00773 00774 //! Initialize variables required to compute the flocking force on the ai char. 00775 unsigned int neighbor_count = 0; 00776 LVecBase3f separation_force = LVecBase3f(0.0, 0.0, 0.0); 00777 LVecBase3f alignment_force = LVecBase3f(0.0, 0.0, 0.0); 00778 LVecBase3f cohesion_force = LVecBase3f(0.0, 0.0, 0.0); 00779 LVecBase3f avg_neighbor_heading = LVecBase3f(0.0, 0.0, 0.0); 00780 LVecBase3f total_neighbor_heading = LVecBase3f(0.0, 0.0, 0.0); 00781 LVecBase3f avg_center_of_mass = LVecBase3f(0.0, 0.0, 0.0); 00782 LVecBase3f total_center_of_mass = LVecBase3f(0.0, 0.0, 0.0); 00783 00784 //! Loop through all the other AI units in the flock to check if they are neigbours. 00785 for(unsigned int i = 0; i < _flock_group->_ai_char_list.size(); i++) { 00786 if(_flock_group->_ai_char_list[i]->_name != _ai_char->_name) { 00787 00788 //! Using visibilty cone to detect neighbors. 00789 LVecBase3f dist_vect = _flock_group->_ai_char_list[i]->_ai_char_np.get_pos() - _ai_char->_ai_char_np.get_pos(); 00790 LVecBase3f ai_char_heading = _ai_char->get_velocity(); 00791 ai_char_heading.normalize(); 00792 00793 //! Check if the current unit is a neighbor. 00794 if(dist_vect.dot(ai_char_heading) > ((dist_vect.length()) * (ai_char_heading.length()) * cos(_flock_group->_flock_vcone_angle * (_PI / 180))) 00795 && (dist_vect.length() < _flock_group->_flock_vcone_radius)) { 00796 //! Separation force calculation. 00797 LVecBase3f ai_char_to_units = _ai_char->_ai_char_np.get_pos() - _flock_group->_ai_char_list[i]->_ai_char_np.get_pos(); 00798 float to_units_dist = ai_char_to_units.length(); 00799 ai_char_to_units.normalize(); 00800 separation_force += (ai_char_to_units / to_units_dist); 00801 00802 //! Calculating the total heading and center of mass of all the neighbors. 00803 LVecBase3f neighbor_heading = _flock_group->_ai_char_list[i]->get_velocity(); 00804 neighbor_heading.normalize(); 00805 total_neighbor_heading += neighbor_heading; 00806 total_center_of_mass += _flock_group->_ai_char_list[i]->_ai_char_np.get_pos(); 00807 00808 //! Update the neighbor count. 00809 ++neighbor_count; 00810 } 00811 } 00812 } 00813 00814 if(neighbor_count > 0) { 00815 //! Alignment force calculation 00816 avg_neighbor_heading = total_neighbor_heading / neighbor_count; 00817 LVector3f ai_char_heading = _ai_char->get_velocity(); 00818 ai_char_heading.normalize(); 00819 avg_neighbor_heading -= ai_char_heading; 00820 avg_neighbor_heading.normalize(); 00821 alignment_force = avg_neighbor_heading; 00822 00823 //! Cohesion force calculation 00824 avg_center_of_mass = total_center_of_mass / neighbor_count; 00825 LVecBase3f cohesion_dir = avg_center_of_mass - _ai_char->_ai_char_np.get_pos(); 00826 cohesion_dir.normalize(); 00827 cohesion_force = cohesion_dir * _ai_char->_movt_force; 00828 } 00829 else if(is_on(_seek) || is_on(_flee) || is_on(_pursue) || is_on(_evade) || is_on(_wander)) { 00830 _flock_done = true; 00831 turn_off("flock"); 00832 turn_on("flock_activate"); 00833 return(LVecBase3f(0.0, 0.0, 0.0)); 00834 } 00835 00836 //! Calculate the resultant force on the ai character by taking into account the separation, alignment and cohesion 00837 //! forces along with their corresponding weights. 00838 return (separation_force * _flock_group->_separation_wt + avg_neighbor_heading * _flock_group->_alignment_wt 00839 + cohesion_force * _flock_group->_cohesion_wt); 00840 } 00841 00842 ///////////////////////////////////////////////////////////////////////////////// 00843 // 00844 // Function : wander 00845 // Description : This function activates wander. 00846 // This is the function we want the user to call for flock to be done. 00847 00848 ///////////////////////////////////////////////////////////////////////////////// 00849 00850 void AIBehaviors::wander(double wander_radius, int flag, double aoe, float wander_weight) { 00851 _wander_obj = new Wander(_ai_char, wander_radius, flag, aoe, wander_weight); 00852 turn_on("wander"); 00853 } 00854 00855 ///////////////////////////////////////////////////////////////////////////////// 00856 // 00857 // Function : obstacle avoidance 00858 // Description : This function activates obstacle avoidance for a given character. 00859 // This is the function we want the user to call for 00860 // obstacle avoidance to be performed. 00861 00862 ///////////////////////////////////////////////////////////////////////////////// 00863 00864 void AIBehaviors::obstacle_avoidance(float obstacle_avoidance_weight) { 00865 _obstacle_avoidance_obj = new ObstacleAvoidance(_ai_char, obstacle_avoidance_weight); 00866 turn_on("obstacle_avoidance_activate"); 00867 } 00868 00869 ///////////////////////////////////////////////////////////////////////////////// 00870 // 00871 // Function : path_follow 00872 // Description : This function activates path following. 00873 // This is the function we want the user to call for path following. 00874 00875 ///////////////////////////////////////////////////////////////////////////////// 00876 00877 void AIBehaviors::path_follow(float follow_wt) { 00878 _path_follow_obj = new PathFollow(_ai_char, follow_wt); 00879 } 00880 00881 ///////////////////////////////////////////////////////////////////////////////// 00882 // 00883 // Function : add_to_path 00884 // Description : This function adds positions to the path to follow. 00885 00886 ///////////////////////////////////////////////////////////////////////////////// 00887 00888 void AIBehaviors::add_to_path(LVecBase3f pos) { 00889 _path_follow_obj->add_to_path(pos); 00890 } 00891 00892 ///////////////////////////////////////////////////////////////////////////////// 00893 // 00894 // Function : start_follow 00895 // Description : This function starts the path follower. 00896 00897 ///////////////////////////////////////////////////////////////////////////////// 00898 00899 void AIBehaviors::start_follow(string type) { 00900 _path_follow_obj->start(type); 00901 } 00902 00903 ///////////////////////////////////////////////////////////////////////////////// 00904 // 00905 // Function : init_path_find 00906 // Description : This function activates path finding in the character. 00907 // This function accepts the meshdata in .csv format. 00908 // 00909 00910 ///////////////////////////////////////////////////////////////////////////////// 00911 00912 void AIBehaviors::init_path_find(const char* navmesh_filename) { 00913 _path_find_obj = new PathFind(_ai_char); 00914 _path_find_obj->set_path_find(navmesh_filename); 00915 } 00916 00917 /////////////////////////////////////////////////////////////////////////////////////// 00918 // 00919 // Function : path_find_to (for pathfinding towards a static position) 00920 // Description : This function checks for the source and target in the navigation mesh 00921 // for its availability and then finds the best path via the A* algorithm 00922 // Then it calls the path follower to make the object follow the path. 00923 00924 /////////////////////////////////////////////////////////////////////////////////////// 00925 00926 void AIBehaviors::path_find_to(LVecBase3f pos, string type) { 00927 _path_find_obj->path_find(pos, type); 00928 } 00929 00930 /////////////////////////////////////////////////////////////////////////////////////// 00931 // 00932 // Function : path_find_to (for pathfinding towards a moving target (a NodePath)) 00933 // Description : This function checks for the source and target in the navigation mesh 00934 // for its availability and then finds the best path via the A* algorithm 00935 // Then it calls the path follower to make the object follow the path. 00936 00937 /////////////////////////////////////////////////////////////////////////////////////// 00938 00939 void AIBehaviors::path_find_to(NodePath target, string type) { 00940 _path_find_obj->path_find(target, type); 00941 } 00942 00943 /////////////////////////////////////////////////////////////////////////////////////// 00944 // 00945 // Function : add_static_obstacle 00946 // Description : This function allows the user to dynamically add obstacles to the 00947 // game environment. The function will update the nodes within the 00948 // bounding volume of the obstacle as non-traversable. Hence will not be 00949 // considered by the pathfinding algorithm. 00950 00951 /////////////////////////////////////////////////////////////////////////////////////// 00952 00953 void AIBehaviors::add_static_obstacle(NodePath obstacle) { 00954 _path_find_obj->add_obstacle_to_mesh(obstacle); 00955 } 00956 00957 /////////////////////////////////////////////////////////////////////////////////////// 00958 // 00959 // Function : add_dynamic_obstacle 00960 // Description : This function starts the pathfinding obstacle navigation for the 00961 // passed in obstacle. 00962 00963 /////////////////////////////////////////////////////////////////////////////////////// 00964 00965 void AIBehaviors::add_dynamic_obstacle(NodePath obstacle) { 00966 _path_find_obj->dynamic_avoid(obstacle); 00967 } 00968 00969 /////////////////////////////////////////////////////////////////////////////////////// 00970 // 00971 // Function : behavior_status 00972 // Description : This function returns the status of an AI Type whether it is active, 00973 // paused or disabled. It returns -1 if an invalid string is passed. 00974 00975 /////////////////////////////////////////////////////////////////////////////////////// 00976 00977 string AIBehaviors::behavior_status(string ai_type) { 00978 switch(char_to_int(ai_type)) { 00979 case 1: 00980 if(_seek_obj) { 00981 if(is_on(_seek)) { 00982 return "active"; 00983 } 00984 else { 00985 if(_seek_obj->_seek_done) { 00986 return "done"; 00987 } 00988 return "paused"; 00989 } 00990 } 00991 else { 00992 return "disabled"; 00993 } 00994 break; 00995 00996 case 2: 00997 if(_flee_obj) { 00998 if(is_on(_flee)) { 00999 unsigned int i = 0; 01000 for(_flee_itr = _flee_list.begin(); _flee_itr != _flee_list.end(); _flee_itr++) { 01001 if(_flee_itr->_flee_done == true) { 01002 ++i; 01003 } 01004 } 01005 if(i == _flee_list.size()) { 01006 return "done"; 01007 } 01008 else { 01009 return "active"; 01010 } 01011 } 01012 else { 01013 return "paused"; 01014 } 01015 } 01016 else { 01017 return "disabled"; 01018 } 01019 break; 01020 01021 case 3: 01022 if(_pursue_obj) { 01023 if(is_on(_pursue)) { 01024 if(_pursue_obj->_pursue_done) { 01025 return "done"; 01026 } 01027 else { 01028 return "active"; 01029 } 01030 } 01031 else { 01032 return "paused"; 01033 } 01034 } 01035 else { 01036 return "disabled"; 01037 } 01038 break; 01039 01040 case 4: 01041 if(_evade_obj) { 01042 if(is_on(_evade)) { 01043 unsigned int i = 0; 01044 for(_evade_itr = _evade_list.begin(); _evade_itr != _evade_list.end(); _evade_itr++) { 01045 if(_evade_itr->_evade_done == true) { 01046 ++i; 01047 } 01048 } 01049 if(i == _evade_list.size()) { 01050 return "done"; 01051 } 01052 else { 01053 return "active"; 01054 } 01055 } 01056 else { 01057 return "paused"; 01058 } 01059 } 01060 else { 01061 return "disabled"; 01062 } 01063 break; 01064 01065 case 5: 01066 if(_arrival_obj) { 01067 if(is_on(_arrival)) { 01068 if(_arrival_obj->_arrival_done) { 01069 return "done"; 01070 } 01071 else { 01072 return "active"; 01073 } 01074 } 01075 else { 01076 return "paused"; 01077 } 01078 } 01079 else { 01080 return "disabled"; 01081 } 01082 break; 01083 01084 case 6: 01085 if(_flock_group) { 01086 if(is_on(_flock)) { 01087 if(_flock_done) { 01088 return "done"; 01089 } 01090 else { 01091 return "active"; 01092 } 01093 return "active"; 01094 } 01095 else { 01096 return "paused"; 01097 } 01098 } 01099 else { 01100 return "disabled"; 01101 } 01102 break; 01103 01104 case 7: 01105 if(_wander_obj) { 01106 if(is_on(_wander)) { 01107 return "active"; 01108 } 01109 else { 01110 return "paused"; 01111 } 01112 } 01113 else { 01114 return "disabled"; 01115 } 01116 break; 01117 01118 case 8: 01119 if(_obstacle_avoidance_obj) { 01120 if(is_on(_obstacle_avoidance)) { 01121 return "active"; 01122 } 01123 else { 01124 return "paused"; 01125 } 01126 } 01127 else { 01128 return "disabled"; 01129 } 01130 break; 01131 01132 case 9: 01133 if(_path_follow_obj) { 01134 if(is_on("pathfollow")) { 01135 if(_pursue_obj->_pursue_done) { 01136 return "done"; 01137 } 01138 else { 01139 return "active"; 01140 } 01141 } 01142 else { 01143 return "paused"; 01144 } 01145 } 01146 else { 01147 return "disabled"; 01148 } 01149 break; 01150 01151 case 16: 01152 if(_path_find_obj) { 01153 if(is_on("pathfind")) { 01154 if(_pursue_obj->_pursue_done) { 01155 return "done"; 01156 } 01157 else { 01158 return "active"; 01159 } 01160 } 01161 else { 01162 return "paused"; 01163 } 01164 } 01165 else { 01166 return "disabled"; 01167 } 01168 break; 01169 01170 case 10: 01171 if(_seek_obj || _flee_obj || _pursue_obj || _evade_obj || _arrival_obj || _flock_group || _wander_obj || _obstacle_avoidance_obj || _path_follow_obj) { 01172 if(is_on(_seek) || is_on(_flee) || is_on(_pursue)|| is_on(_evade) || is_on(_arrival) || is_on(_flock) || is_on(_wander) 01173 || is_on(_obstacle_avoidance) || is_on("pathfollow") || is_on("pathfinding")) { 01174 return "active"; 01175 } 01176 else { 01177 return "paused"; 01178 } 01179 } 01180 else { 01181 return "disabled"; 01182 } 01183 break; 01184 01185 default: 01186 cout<<"Invalid value!"<<endl; 01187 } 01188 } 01189 01190 /////////////////////////////////////////////////////////////////////////////////////// 01191 // 01192 // Function : char_to_int 01193 // Description : This function is used to derive int values from the ai types strings. 01194 // Returns -1 if an invalid string is passed. 01195 01196 /////////////////////////////////////////////////////////////////////////////////////// 01197 01198 int AIBehaviors::char_to_int(string ai_type) { 01199 if(ai_type == "all") { 01200 return 0; 01201 } 01202 else if(ai_type == "seek") { 01203 return 1; 01204 } 01205 else if(ai_type == "flee") { 01206 return 2; 01207 } 01208 else if(ai_type == "pursue") { 01209 return 3; 01210 } 01211 else if(ai_type == "evade") { 01212 return 4; 01213 } 01214 else if(ai_type == "arrival") { 01215 return 5; 01216 } 01217 else if(ai_type == "flock") { 01218 return 6; 01219 } 01220 else if(ai_type == "wander") { 01221 return 7; 01222 } 01223 else if(ai_type == "obstacle_avoidance") { 01224 return 8; 01225 } 01226 else if(ai_type == "pathfollow") { 01227 return 9; 01228 } 01229 else if(ai_type == "any") { 01230 return 10; 01231 } 01232 else if(ai_type == "flee_activate") { 01233 return 11; 01234 } 01235 else if(ai_type == "evade_activate") { 01236 return 12; 01237 } 01238 else if(ai_type == "arrival_activate") { 01239 return 13; 01240 } 01241 else if(ai_type == "flock_activate") { 01242 return 14; 01243 } 01244 else if(ai_type == "obstacle_avoidance_activate") { 01245 return 15; 01246 } 01247 else if(ai_type == "path_finding") { 01248 return 16; 01249 } 01250 01251 return -1; 01252 } 01253 01254 /////////////////////////////////////////////////////////////////////////////////////// 01255 // 01256 // Function : turn_on 01257 // Description : This function turns on any aiBehavior which is passed as a string. 01258 01259 /////////////////////////////////////////////////////////////////////////////////////// 01260 01261 void AIBehaviors::turn_on(string ai_type) { 01262 switch(char_to_int(ai_type)) { 01263 case 1: { 01264 _behaviors_flags |= _seek; 01265 break; 01266 } 01267 case 2: { 01268 _behaviors_flags |= _flee; 01269 break; 01270 } 01271 case 3: { 01272 _behaviors_flags |= _pursue; 01273 break; 01274 } 01275 case 4: { 01276 _behaviors_flags |= _evade; 01277 break; 01278 } 01279 case 5: { 01280 _behaviors_flags |= _arrival; 01281 break; 01282 } 01283 case 6: { 01284 _behaviors_flags |= _flock; 01285 break; 01286 } 01287 case 7: { 01288 _behaviors_flags |= _wander; 01289 break; 01290 } 01291 case 8: { 01292 _behaviors_flags |= _obstacle_avoidance; 01293 break; 01294 } 01295 case 11:{ 01296 _behaviors_flags |= _flee_activate; 01297 break; 01298 } 01299 case 12:{ 01300 _behaviors_flags |= _evade_activate; 01301 break; 01302 } 01303 case 13:{ 01304 _behaviors_flags |= _arrival_activate; 01305 break; 01306 } 01307 case 14:{ 01308 _behaviors_flags |= _flock_activate; 01309 break; 01310 } 01311 case 15:{ 01312 _behaviors_flags |= _obstacle_avoidance_activate; 01313 break; 01314 } 01315 default: 01316 cout<<"Invalid option!"<<endl; 01317 } 01318 } 01319 01320 /////////////////////////////////////////////////////////////////////////////////////// 01321 // 01322 // Function : turn_off 01323 // Description : This function turns off any aiBehavior which is passed as a string. 01324 01325 /////////////////////////////////////////////////////////////////////////////////////// 01326 01327 void AIBehaviors::turn_off(string ai_type) { 01328 switch(char_to_int(ai_type)) { 01329 case 1: { 01330 if (is_on(_seek)) { 01331 _behaviors_flags ^= _seek; 01332 } 01333 _seek_force = LVecBase3f(0.0f, 0.0f, 0.0f); 01334 break; 01335 } 01336 case 2: { 01337 if (is_on(_flee)) { 01338 _behaviors_flags ^= _flee; 01339 } 01340 _flee_force = LVecBase3f(0.0f, 0.0f, 0.0f); 01341 break; 01342 } 01343 case 3: { 01344 if(is_on(_pursue)) { 01345 _behaviors_flags ^= _pursue; 01346 } 01347 _pursue_force = LVecBase3f(0.0f, 0.0f, 0.0f); 01348 break; 01349 } 01350 case 4: { 01351 if(is_on(_evade)) { 01352 _behaviors_flags ^= _evade; 01353 } 01354 _evade_force = LVecBase3f(0.0f, 0.0f, 0.0f); 01355 break; 01356 } 01357 case 5: { 01358 if (is_on(_arrival)) { 01359 _behaviors_flags ^= _arrival; 01360 } 01361 _arrival_force = LVecBase3f(0.0f, 0.0f, 0.0f); 01362 break; 01363 } 01364 case 6: { 01365 if(is_on(_flock)) { 01366 _behaviors_flags ^= _flock; 01367 } 01368 _flock_force = LVecBase3f(0.0f, 0.0f, 0.0f); 01369 break; 01370 } 01371 case 7: { 01372 if(is_on(_wander)) { 01373 _behaviors_flags ^= _wander; 01374 } 01375 _wander_force = LVecBase3f(0.0f, 0.0f, 0.0f); 01376 break; 01377 } 01378 case 8: { 01379 if(is_on(_obstacle_avoidance)) { 01380 _behaviors_flags ^= _obstacle_avoidance; 01381 } 01382 _obstacle_avoidance_force = LVecBase3f(0.0f, 0.0f, 0.0f); 01383 break; 01384 } 01385 case 9:{ 01386 turn_off("pursue"); 01387 break; 01388 } 01389 case 11:{ 01390 if (is_on(_flee_activate)) { 01391 _behaviors_flags ^= _flee_activate; 01392 } 01393 break; 01394 } 01395 case 12:{ 01396 if (is_on(_evade_activate)) { 01397 _behaviors_flags ^= _evade_activate; 01398 } 01399 break; 01400 } 01401 case 13:{ 01402 if (is_on(_arrival_activate)) { 01403 _behaviors_flags ^= _arrival_activate; 01404 } 01405 break; 01406 } 01407 case 14:{ 01408 if (is_on(_flock_activate)) { 01409 _behaviors_flags ^= _flock_activate; 01410 } 01411 break; 01412 } 01413 case 15:{ 01414 if (is_on(_obstacle_avoidance_activate)) { 01415 _behaviors_flags ^= _obstacle_avoidance_activate; 01416 } 01417 break; 01418 } 01419 case 16:{ 01420 turn_off("pathfollow"); 01421 break; 01422 } 01423 default: 01424 cout<<"Invalid option!"<<endl; 01425 } 01426 } 01427 01428 /////////////////////////////////////////////////////////////////////////////////////// 01429 // 01430 // Function : is_on 01431 // Description : This function returns true if an aiBehavior is on 01432 01433 /////////////////////////////////////////////////////////////////////////////////////// 01434 01435 bool AIBehaviors::is_on(_behavior_type bt) { 01436 return (_behaviors_flags & bt) == bt; 01437 } 01438 01439 /////////////////////////////////////////////////////////////////////////////////////// 01440 // 01441 // Function : is_on 01442 // Description : This function returns true if pathfollow or pathfinding is on 01443 01444 /////////////////////////////////////////////////////////////////////////////////////// 01445 01446 bool AIBehaviors::is_on(string ai_type) { 01447 if(ai_type == "pathfollow") { 01448 if(_path_follow_obj) { 01449 return (is_on(_pursue) && _path_follow_obj->_start); 01450 } 01451 else { 01452 return false; 01453 } 01454 } 01455 01456 if(ai_type == "pathfinding") { 01457 if(_path_follow_obj && _path_find_obj) { 01458 return (is_on(_pursue) && _path_follow_obj->_start); 01459 } 01460 else { 01461 return false; 01462 } 01463 } 01464 01465 return false; 01466 } 01467 01468 /////////////////////////////////////////////////////////////////////////////////////// 01469 // 01470 // Function : is_off 01471 // Description : This function returns true if an aiBehavior is off 01472 01473 /////////////////////////////////////////////////////////////////////////////////////// 01474 01475 bool AIBehaviors::is_off(_behavior_type bt) { 01476 return ((_behaviors_flags | bt) == bt); 01477 } 01478 01479 /////////////////////////////////////////////////////////////////////////////////////// 01480 // 01481 // Function : is_off 01482 // Description : This function returns true if pathfollow or pathfinding is off 01483 01484 /////////////////////////////////////////////////////////////////////////////////////// 01485 01486 bool AIBehaviors::is_off(string ai_type) { 01487 if(ai_type == "pathfollow") { 01488 if(_path_follow_obj && _path_follow_obj->_start) { 01489 return true; 01490 } 01491 else { 01492 return false; 01493 } 01494 } 01495 01496 if(ai_type == "pathfinding") { 01497 if(_path_find_obj && _path_follow_obj && _path_follow_obj->_start) { 01498 return true; 01499 } 01500 else { 01501 return false; 01502 } 01503 } 01504 01505 cout<<"You passed an invalid string, defaulting return value to false!"<<endl; 01506 return false; 01507 }