22 #include "pathFollow.h"
31 static const float _PI = 3.14;
33 AIBehaviors::AIBehaviors() {
34 _steering_force = LVecBase3(0.0, 0.0, 0.0);
35 _behaviors_flags = _behaviors_flags & _none;
36 _previous_conflict =
false;
41 _pursue_obj =
nullptr;
43 _arrival_obj =
nullptr;
44 _wander_obj =
nullptr;
45 _flock_group =
nullptr;
46 _path_follow_obj =
nullptr;
47 _path_find_obj =
nullptr;
48 _obstacle_avoidance_obj =
nullptr;
60 AIBehaviors::~AIBehaviors() {
73 if(_previous_conflict ==
false) {
75 _seek_force *= _seek_obj->_seek_weight;
79 LVecBase3 dirn = _flee_force;
81 _flee_force = _steering_force.length() * dirn * _flee_obj->_flee_weight;
85 _pursue_force *= _pursue_obj->_pursue_weight;
89 LVecBase3 dirn = _evade_force;
91 _evade_force = _steering_force.length() * dirn * _evade_obj->_evade_weight;
95 _flock_force *= _flock_weight;
99 _wander_force *= _wander_obj->_wander_weight;
102 _previous_conflict =
true;
110 _previous_conflict =
false;
124 if(force_type ==
"seek") {
125 old_force = _seek_force;
126 _seek_force = old_force + force;
129 if(force_type ==
"flee") {
130 old_force = _flee_force;
131 _flee_force = old_force + force;
134 if(force_type ==
"pursue") {
135 old_force = _pursue_force;
136 double new_force = old_force.length() + force.length();
137 _pursue_force = new_force * _pursue_obj->_pursue_direction;
140 if(force_type ==
"evade") {
141 old_force = _evade_force;
142 double new_force = old_force.length() + force.length();
144 _evade_force = new_force * force;
147 if(force_type ==
"arrival") {
148 _arrival_force = force;
151 if(force_type ==
"flock") {
152 old_force = _flock_force;
153 _flock_force = old_force + force;
156 if(force_type ==
"wander") {
157 old_force = _wander_force;
158 _wander_force = old_force + force;
161 if(force_type ==
"obstacle_avoidance") {
162 old_force = _obstacle_avoidance_force;
163 _obstacle_avoidance_force = old_force +force;
180 force = _seek_obj->
do_seek() * _seek_obj->_seek_weight;
188 if(
is_on(_flee_activate)) {
189 for(_flee_itr = _flee_list.begin(); _flee_itr != _flee_list.end(); _flee_itr++) {
190 _flee_itr->flee_activate();
195 for(_flee_itr = _flee_list.begin(); _flee_itr != _flee_list.end(); _flee_itr++) {
196 if(_flee_itr->_flee_activate_done) {
198 force = _flee_itr->do_flee() * _flee_itr->_flee_weight;
201 force = _flee_itr->do_flee();
210 force = _pursue_obj->
do_pursue() * _pursue_obj->_pursue_weight;
218 if(
is_on(_evade_activate)) {
219 for(_evade_itr = _evade_list.begin(); _evade_itr != _evade_list.end(); _evade_itr++) {
220 _evade_itr->evade_activate();
225 for(_evade_itr = _evade_list.begin(); _evade_itr != _evade_list.end(); _evade_itr++) {
226 if(_evade_itr->_evade_activate_done) {
228 force = (_evade_itr->do_evade()) * (_evade_itr->_evade_weight);
231 force = _evade_itr->do_evade();
238 if(
is_on(_arrival_activate)) {
242 if(
is_on(_arrival)) {
247 if(
is_on(_flock_activate)) {
263 force = _wander_obj->
do_wander() * _wander_obj->_wander_weight;
271 if(
is_on(_obstacle_avoidance_activate)) {
275 if(
is_on(_obstacle_avoidance)) {
285 if(_path_follow_obj!=
nullptr) {
286 if(_path_follow_obj->_start) {
293 _steering_force += _seek_force * int(
is_on(_seek)) + _flee_force * int(
is_on(_flee)) +
294 _pursue_force * int(
is_on(_pursue)) + _evade_force * int(
is_on(_evade)) +
295 _flock_force * int(
is_on(_flock)) + _wander_force * int(
is_on(_wander)) +
296 _obstacle_avoidance_force * int(
is_on(_obstacle_avoidance));
298 if(_steering_force.length() > _ai_char->get_max_force()) {
299 _steering_force.normalize();
300 _steering_force = _steering_force * _ai_char->get_max_force();
303 if(
is_on(_arrival)) {
304 if(_seek_obj !=
nullptr) {
305 LVecBase3 dirn = _steering_force;
307 _steering_force = ((_steering_force.length() - _arrival_force.length()) * dirn);
310 if(_pursue_obj !=
nullptr) {
311 LVecBase3 dirn = _steering_force;
313 _steering_force = ((_steering_force.length() - _arrival_force.length()) * _arrival_obj->_arrival_direction);
316 return _steering_force;
338 if(_seek_obj !=
nullptr) {
347 while (!_flee_list.empty()) {
350 _flee_list.pop_front();
356 if(_pursue_obj !=
nullptr) {
359 _pursue_obj =
nullptr;
365 while (!_evade_list.empty()) {
368 _evade_list.pop_front();
374 if(_arrival_obj !=
nullptr) {
378 _arrival_obj =
nullptr;
384 if(_flock_group !=
nullptr) {
387 _flock_group =
nullptr;
393 if(_wander_obj !=
nullptr) {
396 _wander_obj =
nullptr;
402 if(_obstacle_avoidance_obj !=
nullptr) {
404 delete _obstacle_avoidance_obj;
405 _obstacle_avoidance_obj =
nullptr;
411 if(_pursue_obj !=
nullptr && _path_follow_obj !=
nullptr) {
414 _pursue_obj =
nullptr;
415 delete _path_follow_obj;
416 _path_follow_obj =
nullptr;
421 if(_pursue_obj !=
nullptr && _path_follow_obj !=
nullptr) {
424 _pursue_obj =
nullptr;
425 delete _path_follow_obj;
426 _path_follow_obj =
nullptr;
431 cout<<
"Invalid option!"<<endl;
454 if(_seek_obj !=
nullptr) {
461 for(_flee_itr = _flee_list.begin(); _flee_itr != _flee_list.end(); _flee_itr++) {
469 if(_pursue_obj !=
nullptr) {
476 for(_evade_itr = _evade_list.begin(); _evade_itr != _evade_list.end(); _evade_itr++) {
484 if(_arrival_obj !=
nullptr) {
492 if(_flock_group !=
nullptr) {
500 if(_wander_obj !=
nullptr) {
507 if(_obstacle_avoidance_obj !=
nullptr) {
509 turn_off(
"obstacle_avoidance_activate");
515 if(_pursue_obj !=
nullptr && _path_follow_obj !=
nullptr) {
517 _path_follow_obj->_start =
false;
522 if(_pursue_obj !=
nullptr && _path_follow_obj !=
nullptr) {
524 _path_follow_obj->_start =
false;
529 cout<<
"Invalid option!"<<endl;
552 if(_seek_obj !=
nullptr) {
559 for(_flee_itr = _flee_list.begin(); _flee_itr != _flee_list.end(); _flee_itr++) {
566 if(_pursue_obj !=
nullptr) {
573 for(_evade_itr = _evade_list.begin(); _evade_itr != _evade_list.end(); _evade_itr++) {
580 if(_arrival_obj !=
nullptr) {
587 if(_flock_group !=
nullptr) {
594 if(_wander_obj !=
nullptr) {
601 if(_obstacle_avoidance_obj !=
nullptr) {
608 if(_pursue_obj !=
nullptr && _path_follow_obj !=
nullptr) {
610 _path_follow_obj->_start =
true;
615 if(_pursue_obj !=
nullptr && _path_follow_obj !=
nullptr) {
617 _path_follow_obj->_start =
false;
622 cout<<
"Invalid option!"<<endl;
632 _seek_obj =
new Seek(_ai_char, target_object, seek_wt);
637 _seek_obj =
new Seek(_ai_char, pos, seek_wt);
646 _flee_obj =
new Flee(_ai_char, target_object, panic_distance, relax_distance, flee_wt);
647 _flee_list.insert(_flee_list.end(), *_flee_obj);
652 void AIBehaviors::flee(LVecBase3 pos,
double panic_distance,
double relax_distance,
float flee_wt) {
653 _flee_obj =
new Flee(_ai_char, pos, panic_distance, relax_distance, flee_wt);
654 _flee_list.insert(_flee_list.end(), *_flee_obj);
664 _pursue_obj =
new Pursue(_ai_char, target_object, pursue_wt);
673 _evade_obj =
new Evade(_ai_char, target_object, panic_distance, relax_distance, evade_wt);
674 _evade_list.insert(_evade_list.end(), *_evade_obj);
685 _arrival_obj =
new Arrival(_ai_char, distance);
686 _arrival_obj->_arrival_type =
true;
690 _arrival_obj =
new Arrival(_ai_char, distance);
691 _arrival_obj->_arrival_type =
false;
695 cout<<
"Note: A Seek or Pursue behavior is required to use Arrival behavior."<<endl;
704 _flock_weight = flock_wt;
732 unsigned int neighbor_count = 0;
733 LVecBase3 separation_force = LVecBase3(0.0, 0.0, 0.0);
734 LVecBase3 alignment_force = LVecBase3(0.0, 0.0, 0.0);
735 LVecBase3 cohesion_force = LVecBase3(0.0, 0.0, 0.0);
736 LVecBase3 avg_neighbor_heading = LVecBase3(0.0, 0.0, 0.0);
737 LVecBase3 total_neighbor_heading = LVecBase3(0.0, 0.0, 0.0);
738 LVecBase3 avg_center_of_mass = LVecBase3(0.0, 0.0, 0.0);
739 LVecBase3 total_center_of_mass = LVecBase3(0.0, 0.0, 0.0);
743 for(
unsigned int i = 0; i < _flock_group->_ai_char_list.size(); i++) {
744 if(_flock_group->_ai_char_list[i]->_name != _ai_char->_name) {
747 LVecBase3 dist_vect = _flock_group->_ai_char_list[i]->_ai_char_np.get_pos() - _ai_char->_ai_char_np.
get_pos();
748 LVecBase3 ai_char_heading = _ai_char->get_velocity();
749 ai_char_heading.normalize();
752 if(dist_vect.dot(ai_char_heading) > ((dist_vect.length()) * (ai_char_heading.length()) * cos(_flock_group->_flock_vcone_angle * (_PI / 180)))
753 && (dist_vect.length() < _flock_group->_flock_vcone_radius)) {
755 LVecBase3 ai_char_to_units = _ai_char->_ai_char_np.
get_pos() - _flock_group->_ai_char_list[i]->_ai_char_np.get_pos();
756 float to_units_dist = ai_char_to_units.length();
757 ai_char_to_units.normalize();
758 separation_force += (ai_char_to_units / to_units_dist);
762 LVecBase3 neighbor_heading = _flock_group->_ai_char_list[i]->get_velocity();
763 neighbor_heading.normalize();
764 total_neighbor_heading += neighbor_heading;
765 total_center_of_mass += _flock_group->_ai_char_list[i]->_ai_char_np.get_pos();
773 if(neighbor_count > 0) {
775 avg_neighbor_heading = total_neighbor_heading / neighbor_count;
776 LVector3 ai_char_heading = _ai_char->get_velocity();
777 ai_char_heading.normalize();
778 avg_neighbor_heading -= ai_char_heading;
779 avg_neighbor_heading.normalize();
780 alignment_force = avg_neighbor_heading;
783 avg_center_of_mass = total_center_of_mass / neighbor_count;
784 LVecBase3 cohesion_dir = avg_center_of_mass - _ai_char->_ai_char_np.
get_pos();
785 cohesion_dir.normalize();
786 cohesion_force = cohesion_dir * _ai_char->_movt_force;
792 return(LVecBase3(0.0, 0.0, 0.0));
798 return (separation_force * _flock_group->_separation_wt + avg_neighbor_heading * _flock_group->_alignment_wt
799 + cohesion_force * _flock_group->_cohesion_wt);
807 _wander_obj =
new Wander(_ai_char, wander_radius, flag, aoe, wander_weight);
817 _obstacle_avoidance_obj =
new ObstacleAvoidance(_ai_char, obstacle_avoidance_weight);
818 turn_on(
"obstacle_avoidance_activate");
826 _path_follow_obj =
new PathFollow(_ai_char, follow_wt);
841 _path_follow_obj->
start(type);
850 _path_find_obj =
new PathFind(_ai_char);
902 if(_seek_obj->_seek_done) {
917 for(_flee_itr = _flee_list.begin(); _flee_itr != _flee_list.end(); _flee_itr++) {
918 if(_flee_itr->_flee_done ==
true) {
922 if(i == _flee_list.size()) {
941 if(_pursue_obj->_pursue_done) {
961 for(_evade_itr = _evade_list.begin(); _evade_itr != _evade_list.end(); _evade_itr++) {
962 if(_evade_itr->_evade_done ==
true) {
966 if(i == _evade_list.size()) {
984 if(
is_on(_arrival)) {
985 if(_arrival_obj->_arrival_done) {
1023 if(
is_on(_wander)) {
1036 if(_obstacle_avoidance_obj) {
1037 if(
is_on(_obstacle_avoidance)) {
1050 if(_path_follow_obj) {
1051 if(
is_on(
"pathfollow")) {
1052 if(_pursue_obj->_pursue_done) {
1069 if(_path_find_obj) {
1070 if(
is_on(
"pathfind")) {
1071 if(_pursue_obj->_pursue_done) {
1088 if(_seek_obj || _flee_obj || _pursue_obj || _evade_obj || _arrival_obj || _flock_group || _wander_obj || _obstacle_avoidance_obj || _path_follow_obj) {
1090 ||
is_on(_obstacle_avoidance) ||
is_on(
"pathfollow") ||
is_on(
"pathfinding")) {
1103 cout<<
"Invalid value!"<<endl;
1113 if(ai_type ==
"all") {
1116 else if(ai_type ==
"seek") {
1119 else if(ai_type ==
"flee") {
1122 else if(ai_type ==
"pursue") {
1125 else if(ai_type ==
"evade") {
1128 else if(ai_type ==
"arrival") {
1131 else if(ai_type ==
"flock") {
1134 else if(ai_type ==
"wander") {
1137 else if(ai_type ==
"obstacle_avoidance") {
1140 else if(ai_type ==
"pathfollow") {
1143 else if(ai_type ==
"any") {
1146 else if(ai_type ==
"flee_activate") {
1149 else if(ai_type ==
"evade_activate") {
1152 else if(ai_type ==
"arrival_activate") {
1155 else if(ai_type ==
"flock_activate") {
1158 else if(ai_type ==
"obstacle_avoidance_activate") {
1161 else if(ai_type ==
"path_finding") {
1174 _behaviors_flags |= _seek;
1178 _behaviors_flags |= _flee;
1182 _behaviors_flags |= _pursue;
1186 _behaviors_flags |= _evade;
1190 _behaviors_flags |= _arrival;
1194 _behaviors_flags |= _flock;
1198 _behaviors_flags |= _wander;
1202 _behaviors_flags |= _obstacle_avoidance;
1206 _behaviors_flags |= _flee_activate;
1210 _behaviors_flags |= _evade_activate;
1214 _behaviors_flags |= _arrival_activate;
1218 _behaviors_flags |= _flock_activate;
1222 _behaviors_flags |= _obstacle_avoidance_activate;
1226 cout<<
"Invalid option!"<<endl;
1237 _behaviors_flags ^= _seek;
1239 _seek_force = LVecBase3(0.0f, 0.0f, 0.0f);
1244 _behaviors_flags ^= _flee;
1246 _flee_force = LVecBase3(0.0f, 0.0f, 0.0f);
1250 if(
is_on(_pursue)) {
1251 _behaviors_flags ^= _pursue;
1253 _pursue_force = LVecBase3(0.0f, 0.0f, 0.0f);
1258 _behaviors_flags ^= _evade;
1260 _evade_force = LVecBase3(0.0f, 0.0f, 0.0f);
1264 if (
is_on(_arrival)) {
1265 _behaviors_flags ^= _arrival;
1267 _arrival_force = LVecBase3(0.0f, 0.0f, 0.0f);
1272 _behaviors_flags ^= _flock;
1274 _flock_force = LVecBase3(0.0f, 0.0f, 0.0f);
1278 if(
is_on(_wander)) {
1279 _behaviors_flags ^= _wander;
1281 _wander_force = LVecBase3(0.0f, 0.0f, 0.0f);
1285 if(
is_on(_obstacle_avoidance)) {
1286 _behaviors_flags ^= _obstacle_avoidance;
1288 _obstacle_avoidance_force = LVecBase3(0.0f, 0.0f, 0.0f);
1296 if (
is_on(_flee_activate)) {
1297 _behaviors_flags ^= _flee_activate;
1302 if (
is_on(_evade_activate)) {
1303 _behaviors_flags ^= _evade_activate;
1308 if (
is_on(_arrival_activate)) {
1309 _behaviors_flags ^= _arrival_activate;
1314 if (
is_on(_flock_activate)) {
1315 _behaviors_flags ^= _flock_activate;
1320 if (
is_on(_obstacle_avoidance_activate)) {
1321 _behaviors_flags ^= _obstacle_avoidance_activate;
1330 cout<<
"Invalid option!"<<endl;
1338 return (_behaviors_flags & bt) == bt;
1345 if(ai_type ==
"pathfollow") {
1346 if(_path_follow_obj) {
1347 return (
is_on(_pursue) && _path_follow_obj->_start);
1354 if(ai_type ==
"pathfinding") {
1355 if(_path_follow_obj && _path_find_obj) {
1356 return (
is_on(_pursue) && _path_follow_obj->_start);
1370 return ((_behaviors_flags | bt) == bt);
1377 if(ai_type ==
"pathfollow") {
1378 if(_path_follow_obj && _path_follow_obj->_start) {
1386 if(ai_type ==
"pathfinding") {
1387 if(_path_find_obj && _path_follow_obj && _path_follow_obj->_start) {
1395 cout<<
"You passed an invalid string, defaulting return value to false!"<<endl;