1 | #include "dxstdafx.h"
|
---|
2 | #include ".\aiplayer.h"
|
---|
3 | #include "GameScene.h"
|
---|
4 | #include "Terrain.h"
|
---|
5 | #include "Goodie.h"
|
---|
6 |
|
---|
7 | AIPlayer::AIPlayer(void) : Player() {
|
---|
8 | /*speedCounter = 0;
|
---|
9 | steeringCounter = 3;
|
---|
10 | speedMod = 3;
|
---|
11 | steeringMod = 7;
|
---|
12 | needNewRand = true;*/
|
---|
13 |
|
---|
14 |
|
---|
15 | this->drTimer = 0;
|
---|
16 | this->lastNewPositionTime = 0;
|
---|
17 |
|
---|
18 | this->myState = LEAVE_ISLAND;
|
---|
19 | this->activeOpponent = NULL;
|
---|
20 | this->activeGoodie = NULL;
|
---|
21 |
|
---|
22 | this->frTimer = 0;
|
---|
23 | this->lastFire = 0;
|
---|
24 | srand((UINT)time(NULL));
|
---|
25 | this->nodeType|=GameScene::NODE_AIPLAYER;
|
---|
26 | }
|
---|
27 |
|
---|
28 | AIPlayer::~AIPlayer(void) {
|
---|
29 | }
|
---|
30 |
|
---|
31 | //TODO OPPONENT AND GOODIE SHOULD BE SMART POINTER!!!!!
|
---|
32 | void AIPlayer::update(float dt) {
|
---|
33 | /*if(dt==0) {
|
---|
34 | return;
|
---|
35 | }*/
|
---|
36 |
|
---|
37 | /* #define CHECK_ROTATING 0
|
---|
38 | #define LEAVE_ISLAND 1
|
---|
39 | #define DRIVE_AROUND 2
|
---|
40 | #define ESCAPE 3
|
---|
41 | #define NEAR_GOODIE 4
|
---|
42 | #define NEAR_OPPONENT 5 */
|
---|
43 |
|
---|
44 | Player::update(dt);
|
---|
45 |
|
---|
46 | frTimer+=dt;
|
---|
47 |
|
---|
48 | float ch = ((GameScene *) this->myScene)->getWidth()/2;
|
---|
49 | Vector center(ch, 0, ch);
|
---|
50 | Vector driveToPos;
|
---|
51 | //Vector weaponPos(0, 25, 0);
|
---|
52 | Vector weaponPos(0, 1.25, 0);
|
---|
53 | Vector colPoint;
|
---|
54 | Vector opPos;
|
---|
55 |
|
---|
56 | //Vectors for Obstacle
|
---|
57 | Vector tempHeading;
|
---|
58 | Vector tempObstacle;
|
---|
59 | Vector upV;
|
---|
60 | Vector xV;
|
---|
61 |
|
---|
62 | this->selectWeapon();
|
---|
63 |
|
---|
64 | switch(this->myState) {
|
---|
65 | case CHECK_ROTATING:
|
---|
66 | //Check if vehicle is rotating
|
---|
67 | break;
|
---|
68 | case LEAVE_ISLAND:
|
---|
69 | //Turn and drive back to center of island
|
---|
70 | this->driveTo(dt, center, 0.2f);
|
---|
71 | //this->myScene->manager->printToConsole("LEAVE_ISLAND");
|
---|
72 | break;
|
---|
73 | case NEAR_OBSTACLE:
|
---|
74 | tempHeading = this->heading;
|
---|
75 | tempHeading.y = 0;
|
---|
76 | tempHeading.normalize();
|
---|
77 | tempObstacle = this->obstaclePos - this->getAbsolutePosition();
|
---|
78 | tempObstacle.y = 0;
|
---|
79 | tempObstacle.normalize();
|
---|
80 | upV = tempHeading.crossProd(tempObstacle);
|
---|
81 | upV.normalize();
|
---|
82 | xV = upV.crossProd(tempHeading);
|
---|
83 | driveToPos = tempHeading*5 + xV*10;
|
---|
84 | this->driveTo(dt, driveToPos, 1);
|
---|
85 | break;
|
---|
86 | case NEAR_OPPONENT:
|
---|
87 | //this->myScene->manager->printToConsole("NEAR_OPPONENT");
|
---|
88 | //Select Zone
|
---|
89 | switch(this->myZone) {
|
---|
90 | case COLL_ZONE:
|
---|
91 | //Avoid collistion
|
---|
92 | if(this->activeOpponent!=NULL) {
|
---|
93 | //driveToPos = this->myPosition + (this->myPosition - this->activeOpponent->getPosition())*2*COLL_DIST;
|
---|
94 | driveToPos = this->getAbsolutePosition() + (this->getAbsolutePosition() - this->activeOpponent->getAbsolutePosition())*2*COLL_DIST;
|
---|
95 | this->driveTo(dt, driveToPos, 1);
|
---|
96 | }
|
---|
97 | break;
|
---|
98 | case ATTACK_ZONE:
|
---|
99 | //Try to stay behind activeOpponent and attack him
|
---|
100 | if(this->activeOpponent!=NULL) {
|
---|
101 | driveToPos = this->activeOpponent->getPosition() + (this->activeOpponent->heading)*2*COLL_DIST;
|
---|
102 | this->driveTo(dt, driveToPos, 0.2f);
|
---|
103 |
|
---|
104 | //If theres no intersection, fire at opponent
|
---|
105 | /*opPos = this->activeOpponent->getPosition();
|
---|
106 | colPoint = ((GameScene *) this->myScene)->terrain->collision(this->pos+weaponPos, opPos);
|
---|
107 | if(colPoint.x == opPos.x && colPoint.y == opPos.y && colPoint.z == opPos.z && lastFire+0.8<frTimer) {
|
---|
108 | lastFire = frTimer;
|
---|
109 | this->fire();
|
---|
110 | }*/
|
---|
111 | //TODO verbessern
|
---|
112 |
|
---|
113 | //this->activeWeapon->fire();
|
---|
114 | if(lastFire+1.8<frTimer && ((GameScene*)this->myScene)->aiPlayerFireEnable) {
|
---|
115 | lastFire = frTimer;
|
---|
116 | this->activeWeapon->fire();
|
---|
117 | }
|
---|
118 | }
|
---|
119 | break;
|
---|
120 | case FIRE_ZONE:
|
---|
121 | //Try to attack him if possible!
|
---|
122 | this->driveAround(dt, center, ch);
|
---|
123 | if(this->activeOpponent!=NULL) {
|
---|
124 | /*opPos = this->activeOpponent->getPosition();
|
---|
125 | colPoint = this->sMgr->getTerrain()->collision(this->pos+weaponPos, opPos);
|
---|
126 | if(colPoint.x == opPos.x && colPoint.y == opPos.y && colPoint.z == opPos.z && lastFire+0.8<frTimer) {
|
---|
127 | lastFire = frTimer;
|
---|
128 | this->fire();
|
---|
129 | }*/
|
---|
130 | //TODO verbessern
|
---|
131 |
|
---|
132 | //this->activeWeapon->fire();
|
---|
133 | if(lastFire+1.8<frTimer && ((GameScene*)this->myScene)->aiPlayerFireEnable) {
|
---|
134 | lastFire = frTimer;
|
---|
135 | this->activeWeapon->fire();
|
---|
136 | }
|
---|
137 | }
|
---|
138 | break;
|
---|
139 | }
|
---|
140 | break;
|
---|
141 | case NEAR_GOODIE:
|
---|
142 | //this->myScene->manager->printToConsole("NEAR_GOODIE");
|
---|
143 | if(this->activeGoodie!=NULL) {
|
---|
144 | opPos = this->activeGoodie->getPosition();
|
---|
145 | this->driveTo(dt, opPos, 0.1f);
|
---|
146 | }
|
---|
147 | break;
|
---|
148 | case DRIVE_AROUND:
|
---|
149 | //this->myScene->manager->printToConsole("DRIVE_AROUND");
|
---|
150 | this->driveAround(dt, center, ch);
|
---|
151 | break;
|
---|
152 | }
|
---|
153 |
|
---|
154 | //Calculate next State
|
---|
155 |
|
---|
156 | /*char temp[100];
|
---|
157 | sprintf(temp, "myState = %i", this->myState);
|
---|
158 | this->myScene->manager->printToConsole(temp);*/
|
---|
159 |
|
---|
160 | if(false) {
|
---|
161 | //Solve rotating problem
|
---|
162 | this->myState = CHECK_ROTATING;
|
---|
163 | } else if(isLeaving(center, ch)) { //LEAVE_ISLAND
|
---|
164 | this->myState = LEAVE_ISLAND;
|
---|
165 | } else if(isObstacleNear()) { //NEAR OBSTACLE
|
---|
166 | this->myState = NEAR_OBSTACLE;
|
---|
167 | //this->myScene->manager->printToConsole("NEAR OBSTACLE!");
|
---|
168 | } else if(isNear()) { //NEAR OPPONENT
|
---|
169 | this->myState = NEAR_OPPONENT;
|
---|
170 | } else if(isGoodieNear()) { //NEAR GOODIE
|
---|
171 | this->myState = NEAR_GOODIE;
|
---|
172 | } else { //DRIVE AROUND
|
---|
173 | this->myState = DRIVE_AROUND;
|
---|
174 | }
|
---|
175 |
|
---|
176 | //Player::update(dt);
|
---|
177 |
|
---|
178 | Vector fireAt;
|
---|
179 | if(this->activeOpponent!=NULL) {
|
---|
180 | this->activeOpponent->getAbsoluteVector(fireAt, fireAt);
|
---|
181 | fireAt.y++;
|
---|
182 | this->activeWeapon->setFireAt(fireAt);
|
---|
183 | } else if(this->activeGoodie!=NULL) {
|
---|
184 | this->activeGoodie->getAbsoluteVector(fireAt, fireAt);
|
---|
185 | this->activeWeapon->setFireAt(fireAt);
|
---|
186 | } else {
|
---|
187 | D3DXMATRIX mYaw;
|
---|
188 | Vector fireAt(0,0,1000);
|
---|
189 | //mYaw.setRotateY(this->rot.y*M_PI/180);
|
---|
190 | D3DXMatrixRotationY(&mYaw, this->myRotation.y);
|
---|
191 | fireAt.applyD3DXVector(D3DXVec4Transform(&fireAt, &fireAt, &mYaw));//.transform(fireAt);
|
---|
192 | fireAt = fireAt + this->myPosition;
|
---|
193 | this->getActiveWeapon()->setFireAt(fireAt);
|
---|
194 | }
|
---|
195 |
|
---|
196 | /*char temp[100];
|
---|
197 | Vector tp;
|
---|
198 | this->myScene->manager->printToConsole("---------------");
|
---|
199 | for(int i=0;i<4;i++) {
|
---|
200 | tp = this->wheel[i]->getPosition();
|
---|
201 | sprintf(temp, "x=%f, y=%f z=%f", tp.x, tp.y, tp.z);
|
---|
202 | this->myScene->manager->printToConsole(temp);
|
---|
203 | }*/
|
---|
204 | }
|
---|
205 |
|
---|
206 |
|
---|
207 | bool AIPlayer::isLeaving(Vector center, float ch) {
|
---|
208 | return ((center-this->getAbsolutePosition()).length()>0.9*ch);
|
---|
209 | }
|
---|
210 |
|
---|
211 | bool AIPlayer::isObstacleNear() {
|
---|
212 | NxVec3 direction = this->heading.getNxVector();
|
---|
213 | //direction.y = 0;
|
---|
214 | NxRay ray(this->getAbsolutePosition().getNxVector(), direction);
|
---|
215 | NxRaycastHit hit;
|
---|
216 |
|
---|
217 |
|
---|
218 | // Get the closest shape
|
---|
219 | NxU32 mask = 1<<UserContactReport::COLGROUP_OBSTACLE;
|
---|
220 |
|
---|
221 | NxShape* closestShape = this->myScene->pScene->raycastClosestShape(ray, NX_ALL_SHAPES, hit, mask, 20);//0xffffff);
|
---|
222 | if (closestShape)
|
---|
223 | {
|
---|
224 | this->obstaclePos = Vector(closestShape->getGlobalPosition());
|
---|
225 | return true;
|
---|
226 | } else {
|
---|
227 | return false;
|
---|
228 | }
|
---|
229 | }
|
---|
230 |
|
---|
231 | bool AIPlayer::isNear() {
|
---|
232 | bool isnear = false;
|
---|
233 | int zone = DRIVE_ZONE;
|
---|
234 | Vector opPos;
|
---|
235 | Vector neDir;
|
---|
236 | Vector neHead;
|
---|
237 | float distance;
|
---|
238 | float minDistance=10000000;
|
---|
239 |
|
---|
240 | //std::vector<Player *> *playerList = this->sMgr->getPlayerList();
|
---|
241 | std::list<SPTR<Node> > *playerList = ((GameScene *)this->myScene)->getPlayerList();
|
---|
242 | std::list<SPTR<Node> >::iterator it;
|
---|
243 | Player *tempActiveOpponent = NULL;
|
---|
244 | Player *opponent;
|
---|
245 | //for(unsigned int i=0;i<playerList->size();i++) {
|
---|
246 | for(it=playerList->begin();it!=playerList->end();it++) {
|
---|
247 | //opponent = playerList->at(i);
|
---|
248 | opponent = ((Player *) (*it).get());
|
---|
249 | if(opponent->getTeam()==this->getTeam()) {
|
---|
250 | continue;
|
---|
251 | }
|
---|
252 | if(opponent!=this) {
|
---|
253 | opPos = opponent->getAbsolutePosition();
|
---|
254 | neDir = opPos - this->getAbsolutePosition();
|
---|
255 | distance = neDir.length();
|
---|
256 | neDir.normalize();
|
---|
257 |
|
---|
258 | neHead = this->heading;
|
---|
259 | neHead.normalize();
|
---|
260 | if((neHead.dotProd(neDir))>0) {
|
---|
261 | isnear = true;
|
---|
262 | if(distance<COLL_DIST) {
|
---|
263 | this->myZone = COLL_ZONE;
|
---|
264 | return true;
|
---|
265 | }
|
---|
266 |
|
---|
267 | if(distance<minDistance) {
|
---|
268 | minDistance = distance;
|
---|
269 | tempActiveOpponent = opponent;
|
---|
270 |
|
---|
271 | if(distance<ATTACK_DIST) {
|
---|
272 | this->myZone = ATTACK_ZONE;
|
---|
273 | } else {
|
---|
274 | this->myZone = FIRE_ZONE;
|
---|
275 | }
|
---|
276 | }
|
---|
277 | }
|
---|
278 | }
|
---|
279 | }
|
---|
280 | this->activeOpponent = tempActiveOpponent;
|
---|
281 | return isnear;
|
---|
282 | }
|
---|
283 |
|
---|
284 | bool AIPlayer::isGoodieNear() {
|
---|
285 | bool isnear = false;
|
---|
286 | Vector goPos;
|
---|
287 | Vector goDir;
|
---|
288 | Vector goHead;
|
---|
289 | float distance;
|
---|
290 | float minDistance=10000000;
|
---|
291 |
|
---|
292 | //std::vector<Goodie *> *goodieList = this->sMgr->getGoodieList();
|
---|
293 | std::list<SPTR<Node> > *goodieList = ((GameScene *)this->myScene)->getGoodieList();
|
---|
294 | std::list<SPTR<Node> >::iterator it;
|
---|
295 | Goodie *tempActiveGoodie = NULL;
|
---|
296 | Goodie *goodie;
|
---|
297 | for(unsigned int i=0;i<goodieList->size();i++) {
|
---|
298 | //goodie = goodieList->at(i);
|
---|
299 | goodie = ((Goodie *) (*it).get());
|
---|
300 |
|
---|
301 | goPos = goodie->getPosition();
|
---|
302 | goDir = goPos - this->myPosition;
|
---|
303 | distance = goDir.length();
|
---|
304 | goDir.normalize();
|
---|
305 |
|
---|
306 | goHead = this->heading;
|
---|
307 | goHead.normalize();
|
---|
308 | if((goHead.dotProd(goDir))>0) {
|
---|
309 | isnear = true;
|
---|
310 |
|
---|
311 | if(distance<minDistance) {
|
---|
312 | minDistance = distance;
|
---|
313 | tempActiveGoodie = goodie;
|
---|
314 | }
|
---|
315 | }
|
---|
316 |
|
---|
317 | }
|
---|
318 | this->activeGoodie = tempActiveGoodie;
|
---|
319 | return isnear;
|
---|
320 | }
|
---|
321 |
|
---|
322 | void AIPlayer::driveAround(float dt, Vector center, float ch) {
|
---|
323 | this->drTimer+=dt;
|
---|
324 | if(lastNewPositionTime+3<this->drTimer) {
|
---|
325 | float x = (float)(((float) rand())/(RAND_MAX+1)-0.5)*2*ch;
|
---|
326 | float y = (float)(((float) rand())/(RAND_MAX+1)-0.5)*2*ch;
|
---|
327 | float z = 0;//(float)(((float) rand())/(RAND_MAX+1)-0.5)*2*ch;
|
---|
328 |
|
---|
329 | this->driveToPosition.setXYZ(x, y, z);
|
---|
330 | this->driveToPosition = this->driveToPosition + center;
|
---|
331 | this->lastNewPositionTime = this->drTimer;
|
---|
332 | }
|
---|
333 | this->driveTo(dt, this->driveToPosition, 0.2f);
|
---|
334 | }
|
---|
335 |
|
---|
336 | void AIPlayer::driveTo(float dt, Vector position, float speed) {
|
---|
337 |
|
---|
338 | Vector drDirection;
|
---|
339 | drDirection = position - this->getAbsolutePosition();
|
---|
340 | drDirection.y = 0;
|
---|
341 | drDirection.normalize();
|
---|
342 |
|
---|
343 | Vector drHeading;
|
---|
344 | drHeading = this->heading;
|
---|
345 | drHeading = drHeading*(-1);
|
---|
346 | drHeading.y = 0;
|
---|
347 | drHeading.normalize();
|
---|
348 |
|
---|
349 | Vector drUp(0, 1, 0);
|
---|
350 |
|
---|
351 | //Berechnen ob nach links oder rechts gefahren werden soll
|
---|
352 | Vector drNormDir;
|
---|
353 | drNormDir = drUp.crossProd(drDirection);
|
---|
354 |
|
---|
355 | float leftright = drNormDir.dotProd(drHeading);
|
---|
356 | bool driveLeft = (leftright>0) ? false : true;
|
---|
357 |
|
---|
358 | //Set steering
|
---|
359 | if(leftright!=0) {
|
---|
360 | if(driveLeft)
|
---|
361 | this->toLeft();
|
---|
362 | else
|
---|
363 | this->toRight();
|
---|
364 | }
|
---|
365 |
|
---|
366 | //Set speed
|
---|
367 | //this->accelerate(this->engineTorque<this->maxEngineTorque*speed);
|
---|
368 | if(this->engineForce<this->maxEngineForce*speed*0.5) {
|
---|
369 | this->accelerate();
|
---|
370 | }
|
---|
371 | }
|
---|
372 |
|
---|
373 | void AIPlayer::selectWeapon()
|
---|
374 | {
|
---|
375 | if(this->activeWeapon->getAmo()==0) {
|
---|
376 | for(int i=0;i<10;i++) {
|
---|
377 | if(this->weaponList[i] && this->weaponList[i]->getAmo()>0) {
|
---|
378 | this->setActiveWeapon(i);
|
---|
379 | return;
|
---|
380 | }
|
---|
381 | }
|
---|
382 | }
|
---|
383 | } |
---|