如何實現A星尋路演算法 Cocos2d-x 3 0 beta2
阿新 • • 發佈:2018-12-21
bool pathFound = false;_spOpenSteps.clear();_spClosedSteps.clear();// 首先,新增貓的方塊座標到open列表this->insertInOpenSteps(ShortestPathStep::createWithPosition(fromTileCoord));do{ // 得到最小的F值步驟 // 因為是有序列表,第一個步驟總是最小的F值 ShortestPathStep *currentStep = _spOpenSteps.at(0); // 添加當前步驟到closed列表 _spClosedSteps.pushBack(currentStep); // 將它從open列表裡面移除 // 需要注意的是,如果想要先從open列表裡面移除,應小心物件的記憶體 _spOpenSteps.erase(0); // 如果當前步驟是目標方塊座標,那麼就完成了 if (currentStep->getPosition() == toTileCoord) { pathFound = true; ShortestPathStep *tmpStep = currentStep; CCLOG("PATH FOUND :"); do { CCLOG("%s", tmpStep->getDescription().c_str()); tmpStep = tmpStep->getParent(); // 倒退 } while (tmpStep); // 直到沒有上一步 _spOpenSteps.clear(); _spClosedSteps.clear(); break; } // 得到當前步驟的相鄰方塊座標 PointArray *adjSteps = _layer->walkableAdjacentTilesCoordForTileCoord(currentStep->getPosition()); for (ssize_t i = 0; i < adjSteps->count(); ++i) { ShortestPathStep *step = ShortestPathStep::createWithPosition(adjSteps->getControlPointAtIndex(i)); // 檢查步驟是不是已經在closed列表 if (this->getStepIndex(_spClosedSteps, step) != -1) { continue; } // 計算從當前步驟到此步驟的成本 int moveCost = this->costToMoveFromStepToAdjacentStep(currentStep, step); // 檢查此步驟是否已經在open列表 ssize_t index = this->getStepIndex(_spOpenSteps, step); // 不在open列表,新增它 if (index == -1) { // 設定當前步驟作為上一步操作 step->setParent(currentStep); // G值等同於上一步的G值 + 從上一步到這裡的成本 step->setGScore(currentStep->getGScore() + moveCost); // H值即是從此步驟到目標方塊座標的移動量估算值 step->setHScore(this->computeHScoreFromCoordToCoord(step->getPosition(), toTileCoord)); // 按序新增到open列表 this->insertInOpenSteps(step); } else { // 獲取舊的步驟,其值已經計算過 step = _spOpenSteps.at(index); // 檢查G值是否低於當前步驟到此步驟的值 if ((currentStep->getGScore() + moveCost) < step->getGScore()) { // G值等同於上一步的G值 + 從上一步到這裡的成本 step->setGScore(currentStep->getGScore() + moveCost); // 因為G值改變了,F值也會跟著改變 // 所以為了保持open列表有序,需要將此步驟移除,再重新按序插入 // 在移除之前,需要先保持引用 step->retain(); // 現在可以放心移除,不用擔心被釋放 _spOpenSteps.erase(index); // 重新按序插入 this->insertInOpenSteps(step); // 現在可以釋放它了,因為open列表應該持有它 step->release(); } } }} while (_spOpenSteps.size() > 0);if (!pathFound){ SimpleAudioEngine::getInstance()->playEffect("hitWall.wav");}