00001 00002 00003 00004 00005 00006 00007 00008 00009 00010 00011 00012 00014 00015 #include "aiBehaviors.h" 00016 00017 static const float _PI = 3.14; 00018 00019 AIBehaviors::AIBehaviors() { 00020 _steering_force = LVecBase3f(0.0, 0.0, 0.0); 00021 _behaviors_flags = _behaviors_flags & _none; 00022 _previous_conflict = false; 00023 _conflict = false; 00024 00025 _seek_obj = NULL; 00026 _flee_obj = NULL; 00027 _pursue_obj = NULL; 00028 _evade_obj = NULL; 00029 _arrival_obj = NULL; 00030 _wander_obj = NULL; 00031 _flock_group = NULL; 00032 00033 seek_off(); 00034 flee_off(); 00035 pursue_off(); 00036 evade_off(); 00037 arrival_off(); 00038 flock_off(); 00039 wander_off(); 00040 00041 } 00042 00049 00051 00052 bool AIBehaviors::is_conflict() { 00053 int value = int(On(_seek)) + int(On(_flee)) + int(On(_pursue)) + int(On(_evade)) + int(On(_wander)) + int(On(_flock)); 00054 00055 if(value > 1) { 00056 if(_previous_conflict == false) { 00057 if(On(_seek)) { 00058 _seek_force *= _seek_obj->_seek_weight; 00059 } 00060 00061 if(On(_flee)) { 00062 LVecBase3f dirn = _flee_force; 00063 dirn.normalize(); 00064 _flee_force = _steering_force.length() * dirn * _flee_obj->_flee_weight; 00065 } 00066 00067 if(On(_pursue)) { 00068 _pursue_force *= _pursue_obj->_pursue_weight; 00069 } 00070 00071 if(On(_evade)) { 00072 LVecBase3f dirn = _evade_force; 00073 dirn.normalize(); 00074 _evade_force = _steering_force.length() * dirn * _evade_obj->_evade_weight; 00075 } 00076 00077 if(On(_flock)) { 00078 _flock_force *= _flock_weight; 00079 } 00080 00081 if(On(_wander)) { 00082 _wander_force *= _wander_obj->_wander_weight; 00083 } 00084 00085 _previous_conflict = true; 00086 } 00087 00088 _conflict = true; 00089 return true; 00090 } 00091 00092 _conflict = false; 00093 _previous_conflict = false; 00094 return false; 00095 } 00096 00103 00105 00106 00107 void AIBehaviors::accumulate_force(string force_type, LVecBase3f force) { 00108 00109 LVecBase3f old_force; 00110 00111 if(force_type == "seek") { 00112 old_force = _seek_force; 00113 _seek_force = old_force + force; 00114 } 00115 00116 if(force_type == "flee") { 00117 old_force = _flee_force; 00118 _flee_force = old_force + force; 00119 } 00120 00121 if(force_type == "pursue") { 00122 old_force = _pursue_force; 00123 double new_force = old_force.length() + force.length(); 00124 _pursue_force = new_force * _pursue_obj->_pursue_direction; 00125 } 00126 00127 if(force_type == "evade") { 00128 old_force = _evade_force; 00129 double new_force = old_force.length() + force.length(); 00130 force.normalize(); 00131 _evade_force = new_force * force; 00132 } 00133 00134 if(force_type == "arrival") { 00135 _arrival_force = force; 00136 } 00137 00138 if(force_type == "flock") { 00139 old_force = _flock_force; 00140 _flock_force = old_force + force; 00141 } 00142 00143 if(force_type == "wander") { 00144 old_force = _wander_force; 00145 _wander_force = old_force + force; 00146 } 00147 00148 } 00149 00157 00159 00160 LVecBase3f AIBehaviors::calculate_prioritized() { 00161 LVecBase3f force; 00162 00163 if(is_seek_on()) { 00164 if(_conflict) { 00165 force = _seek_obj->do_seek() * _seek_obj->_seek_weight; 00166 } 00167 else { 00168 force = _seek_obj->do_seek(); 00169 } 00170 00171 accumulate_force("seek",force); 00172 } 00173 00174 if(is_flee_activate_on()) { 00175 for(_flee_itr = _flee_list.begin(); _flee_itr != _flee_list.end(); _flee_itr++) { 00176 _flee_itr->flee_activate(); 00177 } 00178 } 00179 00180 if(is_flee_on()) { 00181 for(_flee_itr = _flee_list.begin(); _flee_itr != _flee_list.end(); _flee_itr++) { 00182 if(_flee_itr->_flee_activate_done) { 00183 if(_conflict) { 00184 force = _flee_itr->do_flee() * _flee_itr->_flee_weight; 00185 } 00186 else { 00187 force = _flee_itr->do_flee(); 00188 } 00189 accumulate_force("flee",force); 00190 } 00191 } 00192 } 00193 00194 if(is_pursue_on()) { 00195 if(_conflict) { 00196 force = _pursue_obj->do_pursue() * _pursue_obj->_pursue_weight; 00197 } 00198 else { 00199 force = _pursue_obj->do_pursue(); 00200 } 00201 accumulate_force("pursue",force); 00202 } 00203 00204 if(is_evade_activate_on()) { 00205 for(_evade_itr = _evade_list.begin(); _evade_itr != _evade_list.end(); _evade_itr++) { 00206 _evade_itr->evade_activate(); 00207 } 00208 } 00209 00210 if(is_evade_on()) { 00211 for(_evade_itr = _evade_list.begin(); _evade_itr != _evade_list.end(); _evade_itr++) { 00212 if(_evade_itr->_evade_activate_done) { 00213 if(_conflict) { 00214 force = (_evade_itr->do_evade()) * (_evade_itr->_evade_weight); 00215 } 00216 else { 00217 force = _evade_itr->do_evade(); 00218 } 00219 accumulate_force("evade",force); 00220 } 00221 } 00222 } 00223 00224 if(is_arrival_activate_on()) { 00225 _arrival_obj->arrival_activate(); 00226 } 00227 00228 if(is_arrival_on()) { 00229 force = _arrival_obj->do_arrival(); 00230 accumulate_force("arrival",force); 00231 } 00232 00233 if(is_flock_activate_on()) { 00234 flock_activate(); 00235 } 00236 00237 if(is_flock_on()) { 00238 if(_conflict) { 00239 force = do_flock() * _flock_weight; 00240 } 00241 else { 00242 force = do_flock(); 00243 } 00244 accumulate_force("flock",force); 00245 } 00246 00247 if(is_wander_on()) { 00248 if(_conflict) { 00249 force = _wander_obj->do_wander() * _wander_obj->_wander_weight; 00250 } 00251 else { 00252 force = _wander_obj->do_wander(); 00253 } 00254 accumulate_force("wander", force); 00255 } 00256 00257 is_conflict(); 00258 00259 _steering_force += _seek_force * int(On(_seek)) + _flee_force * int(On(_flee)) + 00260 _pursue_force * int(On(_pursue)) + _evade_force * int(On(_evade)) + 00261 _flock_force * int(On(_flock)) + _wander_force * int(On(_wander)); 00262 00263 if(_steering_force.length() > _ai_char->get_max_force()) { 00264 _steering_force.normalize(); 00265 _steering_force = _steering_force * _ai_char->get_max_force(); 00266 } 00267 00268 if(On(_arrival)) { 00269 if(_seek_obj != NULL) { 00270 LVecBase3f dirn = _steering_force; 00271 dirn.normalize(); 00272 _steering_force = ((_steering_force.length() - _arrival_force.length()) * dirn); 00273 } 00274 00275 if(_pursue_obj != NULL) { 00276 LVecBase3f dirn = _steering_force; 00277 dirn.normalize(); 00278 _steering_force = ((_steering_force.length() - _arrival_force.length()) * _arrival_obj->_arrival_direction); 00279 } 00280 } 00281 00282 return _steering_force; 00283 } 00284 00289 00291 00292 void AIBehaviors::remove_ai(string ai_type) { 00293 switch(char_to_int(ai_type)) { 00294 case 0: { 00295 remove_ai("seek"); 00296 remove_ai("flee"); 00297 remove_ai("pursue"); 00298 remove_ai("evade"); 00299 remove_ai("arrival"); 00300 remove_ai("flock"); 00301 remove_ai("wander"); 00302 break; 00303 } 00304 00305 case 1: { 00306 if(_seek_obj != NULL) { 00307 seek_off(); 00308 delete _seek_obj; 00309 _seek_obj = NULL; 00310 } 00311 break; 00312 } 00313 00314 case 2: { 00315 while (!_flee_list.empty()) { 00316 flee_off(); 00317 flee_activate_off(); 00318 _flee_list.pop_front(); 00319 } 00320 break; 00321 } 00322 00323 case 3: { 00324 if(_pursue_obj != NULL) { 00325 pursue_off(); 00326 delete _pursue_obj; 00327 _pursue_obj = NULL; 00328 } 00329 break; 00330 } 00331 00332 case 4: { 00333 while (!_evade_list.empty()) { 00334 evade_off(); 00335 evade_activate_off(); 00336 _evade_list.pop_front(); 00337 } 00338 break; 00339 } 00340 00341 case 5: { 00342 if(_arrival_obj != NULL) { 00343 arrival_off(); 00344 arrival_activate_off(); 00345 delete _arrival_obj; 00346 _arrival_obj = NULL; 00347 } 00348 break; 00349 } 00350 00351 case 6: { 00352 if(_flock_group != NULL) { 00353 flock_off(); 00354 flock_activate_off(); 00355 _flock_group = NULL; 00356 } 00357 break; 00358 } 00359 00360 case 7: { 00361 if(_wander_obj != NULL) { 00362 wander_off(); 00363 delete _wander_obj; 00364 _wander_obj = NULL; 00365 } 00366 break; 00367 } 00368 default: 00369 cout<<"Invaled option!"<<endl; 00370 } 00371 } 00372 00377 00379 00380 void AIBehaviors::pause_ai(string ai_type) { 00381 switch(char_to_int(ai_type)) { 00382 case 0: { 00383 pause_ai("seek"); 00384 pause_ai("flee"); 00385 pause_ai("pursue"); 00386 pause_ai("evade"); 00387 pause_ai("arrival"); 00388 pause_ai("flock"); 00389 pause_ai("wander"); 00390 break; 00391 } 00392 00393 case 1: { 00394 if(_seek_obj != NULL) { 00395 seek_off(); 00396 } 00397 break; 00398 } 00399 00400 case 2: { 00401 for(_flee_itr = _flee_list.begin(); _flee_itr != _flee_list.end(); _flee_itr++) { 00402 flee_off(); 00403 flee_activate_off(); 00404 } 00405 break; 00406 } 00407 00408 case 3: { 00409 if(_pursue_obj != NULL) { 00410 pursue_off(); 00411 } 00412 break; 00413 } 00414 00415 case 4: { 00416 for(_evade_itr = _evade_list.begin(); _evade_itr != _evade_list.end(); _evade_itr++) { 00417 evade_off(); 00418 evade_activate_off(); 00419 } 00420 break; 00421 } 00422 00423 case 5: { 00424 if(_arrival_obj != NULL) { 00425 arrival_off(); 00426 arrival_activate_off(); 00427 } 00428 break; 00429 } 00430 00431 case 6: { 00432 if(_flock_group != NULL) { 00433 flock_off(); 00434 flock_activate_off(); 00435 } 00436 break; 00437 } 00438 00439 case 7: { 00440 if(_wander_obj != NULL) { 00441 wander_off(); 00442 } 00443 break; 00444 } 00445 default: 00446 cout<<"Invaled option!"<<endl; 00447 } 00448 } 00449 00454 00456 00457 void AIBehaviors::resume_ai(string ai_type) { 00458 switch(char_to_int(ai_type)) { 00459 case 0: { 00460 resume_ai("seek"); 00461 resume_ai("flee"); 00462 resume_ai("pursue"); 00463 resume_ai("evade"); 00464 resume_ai("arrival"); 00465 resume_ai("flock"); 00466 resume_ai("wander"); 00467 break; 00468 } 00469 00470 case 1: { 00471 if(_seek_obj != NULL) { 00472 seek_on(); 00473 } 00474 break; 00475 } 00476 00477 case 2: { 00478 for(_flee_itr = _flee_list.begin(); _flee_itr != _flee_list.end(); _flee_itr++) { 00479 flee_on(); 00480 } 00481 break; 00482 } 00483 00484 case 3: { 00485 if(_pursue_obj != NULL) { 00486 pursue_on(); 00487 } 00488 break; 00489 } 00490 00491 case 4: { 00492 for(_evade_itr = _evade_list.begin(); _evade_itr != _evade_list.end(); _evade_itr++) { 00493 evade_on(); 00494 } 00495 break; 00496 } 00497 00498 case 5: { 00499 if(_arrival_obj != NULL) { 00500 arrival_on(); 00501 } 00502 break; 00503 } 00504 00505 case 6: { 00506 if(_flock_group != NULL) { 00507 flock_on(); 00508 } 00509 break; 00510 } 00511 00512 case 7: { 00513 if(_wander_obj != NULL) { 00514 wander_on(); 00515 } 00516 break; 00517 } 00518 default: 00519 cout<<"Invaled option!"<<endl; 00520 } 00521 } 00522 00529 00531 00532 void AIBehaviors::seek(NodePath target_object, float seek_wt) { 00533 _seek_obj = new Seek(_ai_char, target_object, seek_wt); 00534 seek_on(); 00535 } 00536 00537 void AIBehaviors::seek(LVecBase3f pos, float seek_wt) { 00538 _seek_obj = new Seek(_ai_char, pos, seek_wt); 00539 seek_on(); 00540 } 00541 00546 00548 00549 bool AIBehaviors::seek_status() { 00550 return(_seek_obj->_seek_done); 00551 } 00552 00558 00560 00561 void AIBehaviors::flee(NodePath target_object, double panic_distance, double relax_distance, float flee_wt) { 00562 _flee_obj = new Flee(_ai_char, target_object, panic_distance, relax_distance, flee_wt); 00563 _flee_list.insert(_flee_list.end(), *_flee_obj); 00564 00565 flee_activate_on(); 00566 } 00567 00568 void AIBehaviors::flee(LVecBase3f pos, double panic_distance, double relax_distance, float flee_wt) { 00569 _flee_obj = new Flee(_ai_char, pos, panic_distance, relax_distance, flee_wt); 00570 _flee_list.insert(_flee_list.end(), *_flee_obj); 00571 00572 flee_activate_on(); 00573 } 00574 00579 00581 00582 bool AIBehaviors::flee_status() { 00583 unsigned int i = 0; 00584 for(_flee_itr = _flee_list.begin(); _flee_itr != _flee_list.end(); _flee_itr++) { 00585 if(_flee_itr->_flee_done == true) { 00586 ++i; 00587 } 00588 } 00589 if(i == _flee_list.size()) { 00590 return true; 00591 } 00592 else { 00593 return false; 00594 } 00595 } 00596 00602 00604 00605 void AIBehaviors::pursue(NodePath target_object, float pursue_wt) { 00606 _pursue_obj = new Pursue(_ai_char, target_object, pursue_wt); 00607 00608 pursue_on(); 00609 } 00610 00615 00617 00618 bool AIBehaviors::pursue_status() { 00619 return(_pursue_obj->_pursue_done); 00620 } 00621 00626 00628 00629 void AIBehaviors::evade(NodePath target_object, double panic_distance, double relax_distance, float evade_wt) { 00630 _evade_obj = new Evade(_ai_char, target_object, panic_distance, relax_distance, evade_wt); 00631 _evade_list.insert(_evade_list.end(), *_evade_obj); 00632 00633 evade_activate_on(); 00634 } 00635 00636 00641 00643 00644 bool AIBehaviors::evade_status() { 00645 unsigned int i = 0; 00646 for(_evade_itr = _evade_list.begin(); _evade_itr != _evade_list.end(); _evade_itr++) { 00647 if(_evade_itr->_evade_done == true) { 00648 ++i; 00649 } 00650 } 00651 if(i == _evade_list.size()) { 00652 return true; 00653 } 00654 else { 00655 return false; 00656 } 00657 } 00658 00664 00666 00667 void AIBehaviors::arrival(NodePath target_object, double distance) { 00668 _arrival_obj = new Arrival(_ai_char, target_object, distance); 00669 00670 arrival_activate_on(); 00671 } 00672 00677 00679 00680 bool AIBehaviors::arrival_status() { 00681 return(_arrival_obj->_arrival_done); 00682 } 00683 00689 00691 00692 void AIBehaviors::flock(float flock_wt) { 00693 _flock_weight = flock_wt; 00694 00695 _flock_done = false; 00696 flock_activate_on(); 00697 } 00698 00703 00705 00706 bool AIBehaviors::flock_status() { 00707 return(_flock_done); 00708 } 00709 00715 00717 00718 void AIBehaviors::flock_activate() { 00719 if(On(_seek) || On(_flee) || On(_pursue) || On(_evade) || On(_wander)) { 00720 flock_activate_off(); 00721 flock_on(); 00722 } 00723 } 00724 00734 00736 00737 LVecBase3f AIBehaviors::do_flock() { 00738 00740 unsigned int neighbor_count = 0; 00741 LVecBase3f separation_force = LVecBase3f(0.0, 0.0, 0.0); 00742 LVecBase3f alignment_force = LVecBase3f(0.0, 0.0, 0.0); 00743 LVecBase3f cohesion_force = LVecBase3f(0.0, 0.0, 0.0); 00744 LVecBase3f avg_neighbor_heading = LVecBase3f(0.0, 0.0, 0.0); 00745 LVecBase3f total_neighbor_heading = LVecBase3f(0.0, 0.0, 0.0); 00746 LVecBase3f avg_center_of_mass = LVecBase3f(0.0, 0.0, 0.0); 00747 LVecBase3f total_center_of_mass = LVecBase3f(0.0, 0.0, 0.0); 00748 00750 for(unsigned int i = 0; i < _flock_group->_ai_char_list.size(); i++) { 00751 if(_flock_group->_ai_char_list[i]->_name != _ai_char->_name) { 00752 00754 LVecBase3f dist_vect = _flock_group->_ai_char_list[i]->_ai_char_np.get_pos() - _ai_char->_ai_char_np.get_pos(); 00755 LVecBase3f ai_char_heading = _ai_char->get_velocity(); 00756 ai_char_heading.normalize(); 00757 00759 if(dist_vect.dot(ai_char_heading) > ((dist_vect.length()) * (ai_char_heading.length()) * cos(_flock_group->_flock_vcone_angle * (_PI / 180))) 00760 && (dist_vect.length() < _flock_group->_flock_vcone_radius)) { 00762 LVecBase3f ai_char_to_units = _ai_char->_ai_char_np.get_pos() - _flock_group->_ai_char_list[i]->_ai_char_np.get_pos(); 00763 float to_units_dist = ai_char_to_units.length(); 00764 ai_char_to_units.normalize(); 00765 separation_force += (ai_char_to_units / to_units_dist); 00766 00768 LVecBase3f neighbor_heading = _flock_group->_ai_char_list[i]->get_velocity(); 00769 neighbor_heading.normalize(); 00770 total_neighbor_heading += neighbor_heading; 00771 total_center_of_mass += _flock_group->_ai_char_list[i]->_ai_char_np.get_pos(); 00772 00774 ++neighbor_count; 00775 } 00776 } 00777 } 00778 00779 if(neighbor_count > 0) { 00781 avg_neighbor_heading = total_neighbor_heading / neighbor_count; 00782 LVector3f ai_char_heading = _ai_char->get_velocity(); 00783 ai_char_heading.normalize(); 00784 avg_neighbor_heading -= ai_char_heading; 00785 avg_neighbor_heading.normalize(); 00786 alignment_force = avg_neighbor_heading; 00787 00789 avg_center_of_mass = total_center_of_mass / neighbor_count; 00790 LVecBase3f cohesion_dir = avg_center_of_mass - _ai_char->_ai_char_np.get_pos(); 00791 cohesion_dir.normalize(); 00792 cohesion_force = cohesion_dir * _ai_char->_movt_force; 00793 } 00794 else if(On(_seek) || On(_flee) || On(_pursue) || On(_evade) || On(_wander)) { 00795 _flock_done = true; 00796 flock_off(); 00797 flock_activate_on(); 00798 return(LVecBase3f(0.0, 0.0, 0.0)); 00799 } 00800 00803 return (separation_force * _flock_group->_separation_wt + avg_neighbor_heading * _flock_group->_alignment_wt 00804 + cohesion_force * _flock_group->_cohesion_wt); 00805 } 00806 00812 00814 00815 void AIBehaviors::wander(double wander_radius, bool flag_3D, double aoe, float wander_weight) { 00816 _wander_obj = new Wander(_ai_char, wander_radius, flag_3D, aoe, wander_weight); 00817 wander_on(); 00818 } 00819 00824 00826 00827 bool AIBehaviors::wander_status() { 00828 if(On(_wander)) { 00829 return false; 00830 } 00831 else { 00832 return true; 00833 } 00834 } 00835 00840 00842 00843 void AIBehaviors::seek_off() { 00844 if (On(_seek)) { 00845 _behaviors_flags ^= _seek; 00846 } 00847 _seek_force = LVecBase3f(0.0f, 0.0f, 0.0f); 00848 } 00849 00850 void AIBehaviors::flee_off() { 00851 if (On(_flee)) { 00852 _behaviors_flags ^= _flee; 00853 } 00854 _flee_force = LVecBase3f(0.0f, 0.0f, 0.0f); 00855 } 00856 00857 void AIBehaviors::pursue_off() { 00858 if(On(_pursue)) { 00859 _behaviors_flags ^= _pursue; 00860 } 00861 _pursue_force = LVecBase3f(0.0f, 0.0f, 0.0f); 00862 } 00863 00864 void AIBehaviors::evade_off() { 00865 if(On(_evade)) { 00866 _behaviors_flags ^= _evade; 00867 } 00868 _evade_force = LVecBase3f(0.0f, 0.0f, 0.0f); 00869 } 00870 00871 void AIBehaviors::arrival_off() { 00872 if (On(_arrival)) { 00873 _behaviors_flags ^= _arrival; 00874 } 00875 _arrival_force = LVecBase3f(0.0f, 0.0f, 0.0f); 00876 } 00877 00878 void AIBehaviors::flock_off() { 00879 if(On(_flock)) { 00880 _behaviors_flags ^= _flock; 00881 } 00882 _flock_force = LVecBase3f(0.0f, 0.0f, 0.0f); 00883 } 00884 00885 void AIBehaviors::wander_off() { 00886 if(On(_wander)) { 00887 _behaviors_flags ^= _wander; 00888 } 00889 _wander_force = LVecBase3f(0.0, 0.0, 0.0); 00890 } 00891 00897 00899 00900 int AIBehaviors::char_to_int(string ai_type) { 00901 if(ai_type == "all") { 00902 return 0; 00903 } 00904 else if(ai_type == "seek") { 00905 return 1; 00906 } 00907 else if(ai_type == "flee") { 00908 return 2; 00909 } 00910 else if(ai_type == "pursue") { 00911 return 3; 00912 } 00913 else if(ai_type == "evade") { 00914 return 4; 00915 } 00916 else if(ai_type == "arrival") { 00917 return 5; 00918 } 00919 else if(ai_type == "flock") { 00920 return 6; 00921 } 00922 else if(ai_type == "wander") { 00923 return 7; 00924 } 00925 return -1; 00926 }