[10029] | 1 | /* |
---|
| 2 | orxonox - the future of 3D-vertical-scrollers |
---|
| 3 | |
---|
| 4 | Copyright (C) 2004 orx |
---|
| 5 | |
---|
| 6 | This program is free software; you can redistribute it and/or modify |
---|
| 7 | it under the terms of the GNU General Public License as published by |
---|
| 8 | the Free Software Foundation; either version 2, or (at your option) |
---|
| 9 | any later version. |
---|
| 10 | |
---|
| 11 | ### File Specific: |
---|
[10045] | 12 | main-programmer: Thomas Fahrni |
---|
[10029] | 13 | co-programmer: |
---|
| 14 | */ |
---|
[10045] | 15 | #define DEBUG_SPECIAL_MODULE DEBUG_MODULE_AI |
---|
[10029] | 16 | |
---|
| 17 | #include "movement_module.h" |
---|
[10045] | 18 | #include "ai_engine.h" |
---|
| 19 | #include "state.h" |
---|
| 20 | #include "debug.h" |
---|
[10071] | 21 | #include "player.h" |
---|
| 22 | #include "playable.h" |
---|
| 23 | #include "aabb.h" |
---|
| 24 | #include "npcs/npc_test.h" |
---|
[10029] | 25 | |
---|
[10071] | 26 | #include "shell_command.h" |
---|
[10112] | 27 | SHELL_COMMAND(setDistanceToPlayer, MovementModule, setDistanceToPlayer); |
---|
| 28 | SHELL_COMMAND(setDistanceToNPC, MovementModule, setDistanceToNPC); |
---|
| 29 | SHELL_COMMAND(setMaxAccleartion, MovementModule, setMaxAccleartion); |
---|
[10071] | 30 | |
---|
[10112] | 31 | float MovementModule::distanceToPlayer=15; |
---|
| 32 | float MovementModule::distanceToNPC=2; |
---|
| 33 | float MovementModule::maxAccleration=200.0f; |
---|
[10071] | 34 | |
---|
[10112] | 35 | void MovementModule::setDistanceToPlayer(float newValue){ distanceToPlayer=newValue; } |
---|
| 36 | void MovementModule::setDistanceToNPC(float newValue){ distanceToNPC=newValue; } |
---|
| 37 | void MovementModule::setMaxAccleartion(float newValue){ maxAccleration=newValue; } |
---|
[10045] | 38 | |
---|
[10029] | 39 | |
---|
| 40 | |
---|
| 41 | |
---|
[10075] | 42 | |
---|
| 43 | |
---|
[10112] | 44 | std::vector<Vector> MovementModule::hidingPoint; |
---|
| 45 | std::vector<float> MovementModule::hidingPointSize; |
---|
[10075] | 46 | |
---|
[10112] | 47 | std::vector<NPC2*> MovementModule::npcList; |
---|
| 48 | std::vector<Vector> MovementModule::npcPosition; |
---|
| 49 | std::vector<float> MovementModule::npcRadius; |
---|
| 50 | std::vector<int> MovementModule::npcSwarm; |
---|
| 51 | std::vector<int> MovementModule::npcTeam; |
---|
[10075] | 52 | |
---|
[10112] | 53 | Vector MovementModule::playerPosition; |
---|
| 54 | Vector MovementModule::playerMovement; |
---|
| 55 | float MovementModule::playerRadius; |
---|
| 56 | |
---|
| 57 | std::vector<Vector> MovementModule::swarmCenter; |
---|
| 58 | std::vector<int> MovementModule::swarmMemberCount; |
---|
| 59 | |
---|
| 60 | |
---|
| 61 | |
---|
| 62 | |
---|
| 63 | |
---|
| 64 | MovementModule::MovementModule(NPC2* object){ this->myNPC=object; } |
---|
| 65 | MovementModule::~MovementModule(){} |
---|
| 66 | |
---|
| 67 | |
---|
| 68 | |
---|
| 69 | |
---|
| 70 | float MovementModule::getRadius(WorldEntity* object) |
---|
[10071] | 71 | { |
---|
| 72 | AABB* aabb = object->getModelAABB(); |
---|
[10112] | 73 | if( aabb == NULL)return -1; |
---|
| 74 | |
---|
| 75 | float a = aabb->halfLength[0]; |
---|
| 76 | float b = aabb->halfLength[1]; |
---|
| 77 | float c = aabb->halfLength[2]; |
---|
[10071] | 78 | |
---|
[10112] | 79 | if(a>b){ |
---|
| 80 | return (c>a)?c:a; |
---|
[10071] | 81 | }else{ |
---|
[10112] | 82 | return (c>b)?c:b; |
---|
[10071] | 83 | } |
---|
| 84 | } |
---|
| 85 | |
---|
| 86 | |
---|
| 87 | |
---|
| 88 | |
---|
[10112] | 89 | void MovementModule::collectInformation(float dt) |
---|
[10041] | 90 | { |
---|
[10112] | 91 | //return if already processed.. |
---|
| 92 | if(dt==this->oldDT)return; |
---|
| 93 | this->oldDT=dt; |
---|
| 94 | |
---|
| 95 | |
---|
| 96 | //clear old Information.. |
---|
| 97 | hidingPoint.clear(); |
---|
| 98 | hidingPointSize.clear(); |
---|
[10029] | 99 | |
---|
[10112] | 100 | npcList.clear(); |
---|
| 101 | npcPosition.clear(); |
---|
| 102 | npcRadius.clear(); |
---|
| 103 | npcSwarm.clear(); |
---|
| 104 | npcTeam.clear(); |
---|
| 105 | |
---|
| 106 | swarmCenter.clear(); |
---|
| 107 | swarmMemberCount.clear(); |
---|
| 108 | |
---|
| 109 | |
---|
| 110 | //get all NPCs.. |
---|
| 111 | for(ObjectList<NPC2>::const_iterator it = NPC2::objectList().begin(); it != NPC2::objectList().end(); ++it) |
---|
| 112 | { |
---|
| 113 | npcList.push_back(*it); |
---|
| 114 | npcRadius.push_back(getRadius(*it)); |
---|
| 115 | npcPosition.push_back((*it)->getAbsCoor()); |
---|
| 116 | npcSwarm.push_back((*it)->swarm); |
---|
| 117 | npcTeam.push_back((*it)->team); |
---|
| 118 | } |
---|
| 119 | |
---|
| 120 | |
---|
| 121 | //Swarm Information |
---|
| 122 | unsigned int tmpSwarm; |
---|
| 123 | for(unsigned int i=0;i<npcList.size();i++){ |
---|
| 124 | tmpSwarm = npcSwarm.at(i); |
---|
| 125 | if(tmpSwarm > swarmMemberCount.size()){ |
---|
| 126 | //swarmMemberCount.insert(swarmMemberCount.size(), tmpSwarm - swarmMemberCount.size(), 0); |
---|
| 127 | //swarmCenter.insert(swarmCenter.size(), tmpSwarm - swarmCenter.size(), Vector(0,0,0)); |
---|
| 128 | } |
---|
| 129 | //swarmMemberCount.at(tmpSwarm)++; |
---|
| 130 | //swarmCenter.at(tmpSwarm)=swarmCenter.at(tmpSwarm)+npcPosition.at(i); |
---|
| 131 | } |
---|
| 132 | for(unsigned int i=0;i<swarmCenter.size();i++){ |
---|
| 133 | //swarmCenter.at(i)=swarmCenter.at(i)/swarmMemberCount.at(i); |
---|
| 134 | } |
---|
| 135 | |
---|
| 136 | |
---|
| 137 | //get information about Player |
---|
[10071] | 138 | Player* pl = State::getPlayer(); |
---|
[10112] | 139 | if( pl != NULL){ |
---|
| 140 | playerPosition = pl->getPlayable()->getAbsCoor(); |
---|
| 141 | playerRadius=getRadius( pl->getPlayable() ); |
---|
| 142 | //PRINTF(0)("Player Radius: %f\n",playerRadius); |
---|
| 143 | } |
---|
| 144 | |
---|
| 145 | |
---|
| 146 | //calculate hiding Points.. |
---|
| 147 | |
---|
| 148 | } |
---|
[10041] | 149 | |
---|
| 150 | |
---|
| 151 | |
---|
| 152 | |
---|
| 153 | |
---|
| 154 | |
---|
| 155 | |
---|
[10071] | 156 | |
---|
| 157 | |
---|
[10112] | 158 | |
---|
| 159 | |
---|
| 160 | |
---|
| 161 | |
---|
| 162 | |
---|
| 163 | void MovementModule::process() |
---|
| 164 | { |
---|
| 165 | this->process(AIEngine::getInstance()->dtS); |
---|
| 166 | } |
---|
| 167 | |
---|
| 168 | |
---|
| 169 | void MovementModule::process(float dt) |
---|
| 170 | { |
---|
| 171 | collectInformation(dt); |
---|
| 172 | |
---|
| 173 | if(myNPC == NULL)return; |
---|
| 174 | |
---|
| 175 | Vector myPosition = myNPC->getAbsCoor(); |
---|
| 176 | float myRadius = getRadius(myNPC); |
---|
| 177 | int mySwarm = myNPC->swarm; |
---|
| 178 | int myTeam = myNPC->team; |
---|
| 179 | |
---|
| 180 | Vector vectorToPlayer = playerPosition - myPosition; |
---|
| 181 | |
---|
| 182 | Vector tmpVector; |
---|
| 183 | float tmpFloat; |
---|
| 184 | |
---|
| 185 | Vector npcCollision; |
---|
| 186 | Vector swarmVector; |
---|
| 187 | Vector playerCollision; |
---|
| 188 | |
---|
| 189 | |
---|
| 190 | |
---|
| 191 | //float a=200.0f; |
---|
| 192 | float vMax=200.0f; |
---|
| 193 | //float safetyDistance=2.0f; |
---|
| 194 | |
---|
| 195 | |
---|
| 196 | //Anti Player Collision |
---|
| 197 | tmpFloat=vectorToPlayer.len()-playerRadius-myRadius-distanceToPlayer; |
---|
| 198 | if(tmpFloat<0.1)tmpFloat=0.1; |
---|
| 199 | playerCollision=vectorToPlayer/(tmpFloat*tmpFloat)*(-1); |
---|
| 200 | |
---|
| 201 | |
---|
| 202 | |
---|
| 203 | for (unsigned int i=0;i<npcList.size();i++) |
---|
[10071] | 204 | { |
---|
[10112] | 205 | if(npcList.at(i)==myNPC)continue; |
---|
[10075] | 206 | |
---|
[10112] | 207 | //Anti NPC Collision |
---|
| 208 | tmpVector=myPosition-npcPosition.at(i); |
---|
| 209 | tmpFloat=tmpVector.len()-myRadius-npcRadius.at(i)-distanceToNPC; |
---|
[10075] | 210 | |
---|
[10112] | 211 | if(tmpFloat<0.1)tmpFloat=0.1; |
---|
| 212 | tmpVector=tmpVector/(tmpFloat*tmpFloat); |
---|
| 213 | |
---|
| 214 | npcCollision=npcCollision+tmpVector; |
---|
| 215 | |
---|
| 216 | //Schwarmverhalten |
---|
| 217 | if(npcSwarm.at(i) == mySwarm){ |
---|
| 218 | |
---|
| 219 | |
---|
| 220 | } |
---|
[10071] | 221 | } |
---|
| 222 | |
---|
| 223 | |
---|
| 224 | |
---|
[10075] | 225 | |
---|
[10112] | 226 | |
---|
| 227 | Vector correction=playerCollision*50+npcCollision*50+vectorToPlayer-myMovement; |
---|
[10071] | 228 | correction.y=0; |
---|
| 229 | float correctionLen=correction.len(); |
---|
[10112] | 230 | if(correctionLen>maxAccleration*dt)correction=correction/correctionLen*maxAccleration*dt; |
---|
| 231 | myMovement+=correction; |
---|
[10071] | 232 | |
---|
[10112] | 233 | float movementLen=myMovement.len(); |
---|
| 234 | if(movementLen>vMax)myMovement/movementLen*vMax; |
---|
[10071] | 235 | |
---|
| 236 | //Move NPC... |
---|
[10112] | 237 | myNPC->shiftCoor(myMovement * dt); |
---|
[10071] | 238 | |
---|
| 239 | //Rotate NPC |
---|
[10112] | 240 | Vector view = myMovement; |
---|
[10075] | 241 | //if(vectorToPlayer.dot(v)<0){ |
---|
| 242 | // view = v.cross( Vector(0,1,0) ).getNormalized(); |
---|
[10071] | 243 | //}else{ |
---|
[10112] | 244 | view = myMovement.cross( Vector(0,-1,0) ).getNormalized(); |
---|
[10071] | 245 | //} |
---|
| 246 | //if(dist<keepDist)view=view*-1; |
---|
[10112] | 247 | //myNPC->setAbsDir( Quaternion( view, Vector(0,1,0))); |
---|
| 248 | myNPC->setAbsDirSoft( Quaternion( view, Vector(0,1,0)),3); |
---|
[10041] | 249 | } |
---|
| 250 | |
---|
| 251 | |
---|