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 }