Guest User

Untitled

a guest
Feb 21st, 2018
53
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 17.26 KB | None | 0 0
  1. /* Copyright Steve Rabin, 2012.
  2. * All rights reserved worldwide.
  3. *
  4. * This software is provided "as is" without express or implied
  5. * warranties. You may freely copy and compile this source into
  6. * applications you distribute provided that the copyright text
  7. * below is included in the resulting source code, for example:
  8. * "Portions Copyright Steve Rabin, 2012"
  9. */
  10. #include <vector>
  11. #include <array>
  12. #include <list>
  13. #include <Stdafx.h>
  14.  
  15. bool Movement::ComputePath( int r, int c, bool newRequest )
  16. {
  17. m_goal = g_terrain.GetCoordinates( r, c );
  18. m_movementMode = MOVEMENT_WAYPOINT_LIST;
  19. // project 2: change this flag to true
  20. bool useAStar = true;
  21. bool returnStatus = false;
  22.  
  23. if( useAStar )
  24. {
  25. ///////////////////////////////////////////////////////////////////////////////////////////////////
  26. //INSERT YOUR A* CODE HERE
  27. //1. You should probably make your own A* class.
  28. //2. You will need to make this function remember the current progress if it preemptively exits.
  29. //3. Return "true" if the path is complete, otherwise "false".
  30. ///////////////////////////////////////////////////////////////////////////////////////////////////
  31. Node* cheapest;
  32.  
  33. D3DXVECTOR3 cur;
  34. float hCost = 0;
  35. Node* start;
  36. Node* goal;
  37. int curR, curC;
  38.  
  39. //get current position
  40. cur = m_owner->GetBody().GetPos();
  41. //get terrain coordinates
  42. g_terrain.GetRowColumn(&cur, &curR, &curC);
  43.  
  44. if (newRequest)
  45. {
  46.  
  47. int mapNum = g_terrain.GetMapIndex();
  48. //reset/Clear data for new search
  49. m_waypointList.clear();
  50.  
  51. if (m_Astar.currentMapIndex != mapNum)
  52. {
  53. m_Astar.LoadNewGrid();
  54. //get map size
  55. m_Astar.currentMapIndex = mapNum;
  56. }
  57. else
  58. m_Astar.ClearGrid();
  59.  
  60. start = m_Astar.a_grid[curR][curC];
  61. goal = m_Astar.a_grid[r][c];
  62. //calculate the new heuristic cost to be used
  63. hCost = m_Astar.CalcHeuristicCost(GetHeuristicCalc(), start, goal);
  64.  
  65. //check for straight line op
  66. if (m_straightline)
  67. {
  68. if (m_Astar.StraightLineOp(start, goal))
  69. {
  70. m_waypointList.push_back(g_terrain.GetCoordinates(curR, curC));
  71. m_waypointList.push_back(g_terrain.GetCoordinates(r, c));
  72. return true;
  73. }
  74. }
  75.  
  76. //push start node onto open list
  77. m_Astar.a_openList.push_back(m_Astar.a_grid[curR][curC]);
  78. }
  79.  
  80. goal = m_Astar.a_grid[r][c];
  81.  
  82. while (!m_Astar.a_openList.empty())
  83. {
  84. //find cheapest node
  85. cheapest = m_Astar.PopCheapest();
  86.  
  87. m_Astar.GetNeighbors(cheapest);
  88.  
  89. //if node is goal node, return found
  90. if (cheapest->x == r && cheapest->y == c)
  91. {
  92. returnStatus = true;
  93. break;
  94. }
  95.  
  96. Node* child = nullptr;
  97. float squareRoot = sqrtf(2.0f);
  98.  
  99. for (int i = 0; i < 8; ++i)
  100. {
  101. child = cheapest->neighbors[i];
  102. if (child != nullptr)
  103. {
  104. float givenC = 0;
  105. int mod = 0;
  106. if (i < 4)
  107. {
  108. givenC = cheapest->givenCost + (i % 2) + squareRoot * ((i + 1) % 2);
  109. }
  110. else
  111. {
  112. mod = 1;
  113. givenC = cheapest->givenCost + ((i + mod) % 2) + squareRoot * ((i + 1 + mod) % 2);
  114. }
  115.  
  116. hCost = m_Astar.CalcHeuristicCost(GetHeuristicCalc(), child, goal);
  117.  
  118. //compute cost: f(x) = g(x) + h(x)
  119. //if child isnt on Open or Closed, put it on Open list
  120. if (child->status == ListStatus::OnOpenList)
  121. {
  122. //check if new cost is cheaper
  123. if (givenC < child->givenCost)
  124. {
  125. child->givenCost = givenC;
  126. child->parent = cheapest;
  127. }
  128. }
  129. else if(child->status == ListStatus::Free)
  130. {
  131. child->givenCost = givenC;
  132. child->totalCost = givenC + (hCost * m_heuristicWeight);
  133. child->parent = cheapest;
  134. child->status = ListStatus::OnOpenList;
  135. m_Astar.a_openList.push_back(child);
  136. if (!g_terrain.IsWall(cheapest->x, cheapest->y))
  137. g_terrain.SetColor(child->x, child->y, DEBUG_COLOR_CYAN);
  138. }
  139. }
  140. }
  141.  
  142. //Place parent node on Closed List
  143. cheapest->status = ListStatus::OnClosedList;
  144. if(!g_terrain.IsWall(cheapest->x, cheapest->y))
  145. g_terrain.SetColor(cheapest->x, cheapest->y, DEBUG_COLOR_YELLOW);
  146.  
  147. if (m_singleStep)
  148. return false; //return working
  149. }//End of while
  150.  
  151. if (returnStatus)
  152. {
  153. if (m_rubberband)
  154. m_Astar.RubberBandPath(cheapest);
  155.  
  156. if (m_smooth)
  157. {
  158. Node* current = cheapest;
  159. std::vector<D3DXVECTOR3> pointList;
  160.  
  161. while (current != nullptr)
  162. {
  163. m_waypointList.push_front(g_terrain.GetCoordinates(current->x, current->y));
  164. pointList.push_back(g_terrain.GetCoordinates(current->x, current->y));
  165. current = current->parent;
  166.  
  167. }
  168.  
  169. CatmullSmoothing(pointList);
  170. }
  171. else
  172. {
  173. Node* current = cheapest;
  174. while (current != nullptr)
  175. {
  176. m_waypointList.push_front(g_terrain.GetCoordinates(current->x, current->y));
  177. current = current->parent;
  178.  
  179. }
  180. }
  181. }
  182. else if (m_Astar.a_openList.empty())
  183. {
  184. m_waypointList.clear();
  185. m_waypointList.push_back(g_terrain.GetCoordinates(curR, curC));
  186. return true;
  187. }
  188.  
  189. return returnStatus;
  190. }
  191. else
  192. {
  193. //Randomly meander toward goal (might get stuck at wall)
  194. int curR, curC;
  195. D3DXVECTOR3 cur = m_owner->GetBody().GetPos();
  196. g_terrain.GetRowColumn( &cur, &curR, &curC );
  197.  
  198. m_waypointList.clear();
  199. m_waypointList.push_back( cur );
  200.  
  201. int countdown = 100;
  202. while( curR != r || curC != c )
  203. {
  204. if( countdown-- < 0 ) { break; }
  205.  
  206. if( curC == c || (curR != r && rand()%2 == 0) )
  207. { //Go in row direction
  208. int last = curR;
  209. if( curR < r ) { curR++; }
  210. else { curR--; }
  211.  
  212. if( g_terrain.IsWall( curR, curC ) )
  213. {
  214. curR = last;
  215. continue;
  216. }
  217. }
  218. else
  219. { //Go in column direction
  220. int last = curC;
  221. if( curC < c ) { curC++; }
  222. else { curC--; }
  223.  
  224. if( g_terrain.IsWall( curR, curC ) )
  225. {
  226. curC = last;
  227. continue;
  228. }
  229. }
  230.  
  231. D3DXVECTOR3 spot = g_terrain.GetCoordinates( curR, curC );
  232. m_waypointList.push_back( spot );
  233. g_terrain.SetColor( curR, curC, DEBUG_COLOR_YELLOW );
  234. }
  235. return true;
  236. }
  237. }
  238.  
  239. // POP CHEAPEST
  240. Node* A_Star::PopCheapest()
  241. {
  242. Node* cheapest = a_openList.front();
  243.  
  244. if (a_openList.size() == 1)
  245. {
  246. Node* temp = a_openList.back();
  247. a_openList.pop_back();
  248. return temp;
  249. }
  250.  
  251. int index = 0;
  252. int counter = 0;
  253.  
  254. for (std::vector<Node*>::iterator it = a_openList.begin(); it != a_openList.end(); ++it)
  255. {
  256. if ((*it)->totalCost < cheapest->totalCost)
  257. {
  258. cheapest = *it;
  259. index = counter;
  260. }
  261. ++counter;
  262. }
  263.  
  264. //swap end node with cheapest and pop back()
  265. Node* temp = a_openList.back();
  266. a_openList.back() = cheapest;
  267. //eapest = temp;
  268. a_openList[index] = temp;
  269. temp = a_openList.back();
  270. temp->status = ListStatus::OnClosedList;
  271. a_openList.pop_back();
  272. return temp;
  273. }
  274.  
  275. // CALC HEURISTIC COSTS
  276. float A_Star::CalcHeuristicCost(int method, Node* start, Node* goal)
  277. {
  278. float result = 0;
  279. float xDiff;
  280. float yDiff;
  281.  
  282. switch (method)
  283. {
  284. case 0: //euclid
  285. xDiff = abs(goal->x - start->x);
  286. yDiff = abs(goal->y - start->y);
  287. result = sqrt((xDiff * xDiff) + (yDiff * yDiff));
  288. break;
  289. case 1: //octile
  290. xDiff = abs(goal->x - start->x);
  291. yDiff = abs(goal->y - start->y);
  292. result = (min(xDiff, yDiff) * sqrt(2)) + (max(xDiff, yDiff) - min(xDiff, yDiff));
  293. break;
  294. case 2: //cheby
  295. result = max(abs(goal->x - start->x), abs(goal->y - start->y));
  296. break;
  297. case 3: //manhattan
  298. result = abs(goal->x - start->x) + abs(goal->y - start->y);
  299. break;
  300. }
  301.  
  302. return result;
  303. }
  304.  
  305. // RUBBERBAND PATH
  306. void A_Star::RubberBandPath(Node * goalNode)
  307. {
  308. Node* firstNode = goalNode; //should be the goal node at this point
  309. Node* secondNode = firstNode->parent;
  310. Node* thirdNode = firstNode->parent->parent;
  311. int maxX, maxY, minX, minY;
  312.  
  313. if (secondNode == nullptr)
  314. return;
  315.  
  316. while (thirdNode != nullptr)
  317. {
  318. //set bounds for x
  319. maxX = max(firstNode->x, thirdNode->x);
  320. minX = min(firstNode->x, thirdNode->x);
  321.  
  322. //set bounds for y
  323. maxY = max(firstNode->y, thirdNode->y);
  324. minY = min(firstNode->y, thirdNode->y);
  325.  
  326. bool abort = false;
  327.  
  328. //test for walls to band around
  329. for (int i = minX; i <= maxX; ++i)
  330. {
  331. for (int j = minY; j <= maxY; ++j)
  332. {
  333. if (g_terrain.IsWall(i, j))
  334. {
  335. abort = true;
  336. break;
  337. }
  338. else
  339. {
  340. firstNode->parent = thirdNode;
  341. }
  342. }
  343.  
  344. if (abort)
  345. break;
  346. }
  347.  
  348. //now check for new nodes to evaluate
  349. firstNode = thirdNode;
  350. secondNode = firstNode->parent;
  351. thirdNode = firstNode->parent->parent;
  352. }
  353. }
  354.  
  355. // ROM SPLINING / SMOOTHING
  356. void Movement::CatmullSmoothing(std::vector<D3DXVECTOR3> pointList)
  357. {
  358. std::vector<D3DXVECTOR3> points = pointList;
  359. unsigned pathSize = 0;
  360. unsigned psize = points.size();
  361. if (psize == 1)
  362. {
  363. m_waypointList.push_back(points[0]);
  364. return;
  365. }
  366.  
  367. std::vector<D3DXVECTOR3> newPoints;
  368. if (m_rubberband)
  369. {
  370. unsigned pos = 0;
  371.  
  372. for (unsigned i = 0; i < psize - 1; i++, pos++)
  373. {
  374. int r, c;
  375. D3DXVECTOR3 v1 = points[i];
  376. D3DXVECTOR3 v2 = points[i + 1];
  377. float distance = GetDistance(v1, v2);
  378.  
  379. if (distance > 1.49f)
  380. {
  381. int add = (int)(distance / 1.5) + 1;
  382. D3DXVECTOR3 step = (v2 - v1) / (float)add;
  383. for (int j = 0; j < add; j++)
  384. {
  385. newPoints.push_back(v1 + step * (float)(j));
  386. }
  387. }
  388. else
  389. newPoints.push_back(v1);
  390. }
  391.  
  392. newPoints.push_back(points[psize - 1]);
  393. }
  394.  
  395. if (newPoints.size() < psize)
  396. newPoints = points;
  397.  
  398. for (unsigned i = 0; i < newPoints.size() - 1; i++)
  399. {
  400. D3DXVECTOR3 p2 = newPoints[i];
  401. D3DXVECTOR3 p3 = newPoints[i + 1];
  402.  
  403. D3DXVECTOR3 p1;
  404. if (i == 0)
  405. p1 = p2;
  406. else
  407. p1 = newPoints[i - 1];
  408.  
  409. D3DXVECTOR3 p4;
  410. if (i == newPoints.size() - 2)
  411. p4 = p3;
  412. else
  413. p4 = newPoints[i + 2];
  414. m_waypointList.push_front(p2);
  415. for (int j = 1; j < 4; j++)
  416. {
  417. D3DXVECTOR3 out;
  418. D3DXVec3CatmullRom(&out, &p1, &p2, &p3, &p4, 0.25f * j);
  419. m_waypointList.push_front(out);
  420. }
  421. }
  422. }
  423.  
  424. // DISTANCE FUNCTION
  425. float Movement::GetDistance(D3DXVECTOR3 c1, D3DXVECTOR3 c2)
  426. {
  427. //(Dx*Dx+Dy*Dy+Dz*Dz)^.5
  428. float dx = c2.x - c1.x;
  429. float dy = c2.y - c1.y;
  430. float dz = c2.z - c1.z;
  431.  
  432. return sqrt((float)(dx * dx + dy * dy + dz * dz));
  433. }
  434.  
  435. // STRAIGHT LINE OPTIMIZATION
  436. bool A_Star::StraightLineOp(Node * startNode, Node * goalNode)
  437. {
  438. int maxX, maxY, minX, minY;
  439.  
  440. //set bounds for x
  441. if (startNode->x > goalNode->x)
  442. {
  443. maxX = startNode->x;
  444. minX = goalNode->x;
  445. }
  446. else
  447. {
  448. maxX = goalNode->x;
  449. minX = startNode->x;
  450. }
  451. //set bounds for y
  452. if (startNode->y > goalNode->y)
  453. {
  454. maxY = startNode->y;
  455. minY = goalNode->y;
  456. }
  457. else
  458. {
  459. maxY = goalNode->y;
  460. minY = startNode->y;
  461. }
  462.  
  463. bool abort = false;
  464.  
  465. //test for walls between start and goal
  466. for (int i = minX; i <= maxX; ++i)
  467. {
  468. for (int j = minY; j <= maxY; ++j)
  469. {
  470. if (g_terrain.IsWall(i, j))
  471. {
  472. return false;
  473. }
  474. }
  475. }
  476.  
  477. return true;
  478. }
  479.  
  480. // LOAD NEW GRID
  481. void A_Star::LoadNewGrid()
  482. {
  483. int currentMapSize = g_terrain.GetWidth();
  484. a_openList.clear();
  485.  
  486. for (int i = 0; i < currentMapSize; ++i)
  487. {
  488. for (int j = 0; j < currentMapSize; ++j)
  489. {
  490. if (g_terrain.IsWall(i, j))
  491. {
  492. a_grid[i][j] = nullptr;
  493. continue;
  494. }
  495.  
  496. a_grid[i][j] = new Node();
  497. a_grid[i][j]->x = i;
  498. a_grid[i][j]->y = j;
  499. g_terrain.SetColor(i, j, DEBUG_COLOR_WHITE);
  500. }
  501. }
  502. }
  503.  
  504. void A_Star::ClearGrid()
  505. {
  506. a_openList.clear();
  507.  
  508. for (int i = 0; i < g_terrain.GetWidth(); ++i)
  509. {
  510. for (int j = 0; j < g_terrain.GetWidth(); ++j)
  511. {
  512. if (a_grid[i][j] != nullptr)
  513. {
  514. a_grid[i][j]->parent = nullptr;
  515. a_grid[i][j]->givenCost = 0;
  516. a_grid[i][j]->totalCost = 0;
  517. a_grid[i][j]->status = ListStatus::Free;
  518.  
  519. if (!g_terrain.IsWall(i, j))
  520. g_terrain.SetColor(i, j, DEBUG_COLOR_WHITE);
  521. }
  522. }
  523. }
  524. }
  525.  
  526. // GET NEIGHBORS
  527. void A_Star::GetNeighbors(Node* node)
  528. {
  529. int curX = node->x;
  530. int curY = node->y;
  531.  
  532. node->neighbors[0] = a_grid[curX - 1][curY + 1];
  533. node->neighbors[1] = a_grid[curX][curY + 1];
  534. node->neighbors[2] = a_grid[curX + 1][curY + 1];
  535.  
  536. node->neighbors[3] = a_grid[curX - 1][curY];
  537. node->neighbors[4] = a_grid[curX + 1][curY];
  538.  
  539. node->neighbors[5] = a_grid[curX - 1][curY - 1];
  540. node->neighbors[6] = a_grid[curX][curY - 1];
  541. node->neighbors[7] = a_grid[curX + 1][curY - 1];
  542.  
  543. //bounds check x
  544. if (node->x == 0)
  545. {
  546. node->neighbors[0] = nullptr;
  547. node->neighbors[3] = nullptr;
  548. node->neighbors[5] = nullptr;
  549. }
  550. else if (node->x == g_terrain.GetWidth() - 1)
  551. {
  552. node->neighbors[2] = nullptr;
  553. node->neighbors[4] = nullptr;
  554. node->neighbors[7] = nullptr;
  555. }
  556.  
  557. //bounds check y
  558. if (node->y == 0)
  559. {
  560. node->neighbors[5] = nullptr;
  561. node->neighbors[6] = nullptr;
  562. node->neighbors[7] = nullptr;
  563. }
  564. else if (node->y == g_terrain.GetWidth() - 1)
  565. {
  566. node->neighbors[0] = nullptr;
  567. node->neighbors[1] = nullptr;
  568. node->neighbors[2] = nullptr;
  569. }
  570.  
  571. //wall check
  572. for (int i = 0; i < 8; ++i)
  573. {
  574. /* 0 / 1 / 2 //
  575. // 3 / n / 4 //
  576. // 5 / 6 / 7 */
  577. if (node->neighbors[i] != nullptr) //if this is an actual node
  578. {
  579. if (g_terrain.IsWall(node->neighbors[i]->x, node->neighbors[i]->y))
  580. {
  581. node->neighbors[i] = nullptr; //its a wall, we use nullptrs for your kind
  582. continue;
  583. }
  584.  
  585. // CHECK YOUR CORNERS MATE //
  586. //now check for corner squares
  587. //check top left
  588. if (i == 0)
  589. {
  590. if (node->neighbors[1] == nullptr)
  591. {
  592. node->neighbors[0] = nullptr;
  593. }
  594.  
  595. if(node->neighbors[3] == nullptr)
  596. {
  597. node->neighbors[0] = nullptr;
  598. }
  599. }
  600. //top right
  601. else if (i == 2)
  602. {
  603. if (node->neighbors[1] == nullptr)
  604. {
  605. node->neighbors[2] = nullptr;
  606. }
  607.  
  608. if (node->neighbors[4] == nullptr)
  609. {
  610. node->neighbors[2] = nullptr;
  611. }
  612. }
  613. //bottom left
  614. else if (i == 5)
  615. {
  616. if (node->neighbors[3] == nullptr)
  617. {
  618. node->neighbors[5] = nullptr;
  619. }
  620.  
  621. if (node->neighbors[6] == nullptr)
  622. {
  623. node->neighbors[5] = nullptr;
  624. }
  625. }
  626. //bottom right
  627. else if (i == 7)
  628. {
  629. if (node->neighbors[4] == nullptr)
  630. {
  631. node->neighbors[7] = nullptr;
  632. }
  633.  
  634. if (node->neighbors[6] == nullptr)
  635. {
  636. node->neighbors[7] = nullptr;
  637. }
  638. }
  639. }
  640. }
  641. }
Add Comment
Please, Sign In to add comment