1. 程式人生 > >如何實現A星尋路演算法 Cocos2d-x 3 0 beta2

如何實現A星尋路演算法 Cocos2d-x 3 0 beta2

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");}