标题:cocos2d-x实现的A*寻路
取消只看楼主
BlueGuy
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:29
帖 子:4476
专家分:4055
注 册:2009-4-18
结帖率:94.72%
 问题点数:0 回复次数:0 
cocos2d-x实现的A*寻路
下载链接:https://down.bccn.net/10527.html,工程使用的是cocos2d-x-2.2.6版本
程序代码:
#include <stdlib.h>
#include "PathFind.h"

PathFind::PathFind()
{
}

PathFind::~PathFind()
{
}

static PathFind* pathFind = NULL;

PathFind* PathFind::getTheOnlyInstance()
{
    if (!pathFind)
    {
        pathFind = new PathFind();
    }

    return pathFind;
}

// A*初始化
Astar* PathFind::newAstar()
{
    Astar* astar = (Astar*)malloc(sizeof(Astar));
    astar->openHead = (AstartListNode*)malloc(sizeof(AstartListNode));
    astar->closedHead = (AstartListNode*)malloc(sizeof(AstartListNode));
    astar->openHead->next = NULL;
    astar->closedHead->next = NULL;
    return astar;
}

// A*释放
void PathFind::deleteAstar(Astar* astar)
{
    while (astar->openHead != NULL)
    {
        AstartListNode* t = astar->openHead;
        astar->openHead = astar->openHead->next;
        free(t);
        t = NULL;
    }

    while (astar->closedHead != NULL)
    {
        AstartListNode* t = astar->closedHead;
        astar->closedHead = astar->closedHead->next;
        free(t);
        t = NULL;
    }

    free(astar);
}

// 结点初始化
void PathFind::AstarNodeInit(AstartListNode* current, AstartListNode* father, int x, int y, int endX, int endY)
{
    current->x = x;
    current->y = y;
    current->father = father;
    current->next = NULL;

    if (father != NULL)
    {
        current->f = father->f + 1;
    }
    else
    {
        current->f = 0;
    }

    current->g = abs(endX - x) + abs(endY - y);
    current->h = current->f + current->g;
}

// 取得成本最小的结点
AstartListNode* PathFind::AstarGetMinCostList(Astar* astar)
{
    AstartListNode* min = astar->openHead->next;
    AstartListNode* current = min->next;

    while (current != NULL)
    {
        if (current->h < min->h)
        {
            min = current;
        }

        current = current->next;
    }

    return min;
}

// 添加结点到链表
void PathFind::AstarAddNode(AstartListNode* head, AstartListNode* node)
{
    while (head->next != NULL)
    {
        head = head->next;
    }

    head->next = node;
}

// 从链表中删除结点
void PathFind::AstarRemoveNode(AstartListNode* head, AstartListNode* node)
{
    AstartListNode* current = head;
    head = head->next;

    while (head != NULL)
    {
        if (head == node)
        {
            current->next = head->next;
            head->next = NULL;
            break;
        }
        else
        {
            current = head;
            head = head->next;
        }
    }
}

// 检查Tile是否在链表中
bool PathFind::AstarCheckNodeInList(int x, int y, AstartListNode* head)
{
    bool result = false;
    head = head->next;

    while (head != NULL)
    {
        if (head->x == x && head->y == y)
        {
            result = true;
            break;
        }
        else
        {
            head = head->next;
        }
    }

    return result;
}

// 检查Tile是否是地图的路障
bool PathFind::AstarIsBlock(int x, int y)
{
    if (x >= 0 && x < tiledMap->getMapSize().width && y >= 0 && y < tiledMap->getMapSize().height)
    {    
        CCTMXLayer* mapLayer = tiledMap->layerNamed("mainCityLayer");
        unsigned int gid = mapLayer->tileGIDAt(ccp(x, y));

        CCDictionary* tileProperty = tiledMap->propertiesForGID(gid);
        int v = ((CCString*)tileProperty->objectForKey("walk"))->intValue();

        if (v == 0)
        {
            return true;
        }
    }
    else
    {
        return false;
    }

    return false;
}

bool PathFind::AStarSearch(CCTMXTiledMap* tiledMap, int startX, int startY, int endX, int endY)
{
    astarPathCount = 0;
    astarPathList.clear();

    this->tiledMap = tiledMap;

    this->startX = startX;
    this->startY = startY;
    this->endX = endX;
    this->endY = endY;

    if (AstarIsBlock(endX, endY))
    {
        return false;
    }

    int offsetX[] = {0, 0, -1, 1, -1, -1, 1, 1};
    int offsetY[] = {1, -1, 0, 0, 1, -1, 1, -1};
    
    Astar* astar = newAstar();

    AstartListNode* currentNode = NULL;
    AstartListNode* startNode = (AstartListNode*)malloc(sizeof(AstartListNode));
    AstarNodeInit(startNode, NULL, startX, startY, endX, endY);
    // 把起始结点加入OpenList
    AstarAddNode(astar->openHead, startNode);

    // 如查OpenList不为空
    while (astar->openHead->next != NULL)
    {
        // 取得成本最小的结点
        currentNode = AstarGetMinCostList(astar);

        // 如果当前结点是目标结点
        if (currentNode->x == endX && currentNode->y == endY)
        {
            break;
        }
        else
        {
            // 把当前结点添加到Closed表中
            AstarAddNode(astar->closedHead, currentNode);
            // 把当前结点从Open表中删除
            AstarRemoveNode(astar->openHead, currentNode);

            for (int i = 0; i < 8; i++)
            {
                int x = currentNode->x + offsetX[i];
                int y = currentNode->y + offsetY[i];

                if (x < 0 || x >= tiledMap->getMapSize().width || y < 0 || y >= tiledMap->getMapSize().height)
                {
                    continue;
                }
                else
                {
                    if (!AstarCheckNodeInList(x, y, astar->openHead)
                        && !AstarCheckNodeInList(x, y, astar->closedHead)
                        && !AstarIsBlock(x, y)
                       )
                    {
                        AstartListNode* endNode = (AstartListNode*)malloc(sizeof(AstartListNode));
                        AstarNodeInit(endNode, currentNode, x, y, endX, endY);
                        AstarAddNode(astar->openHead, endNode);
                    }
                }
            }
        }
    }

    if (astar->openHead->next == NULL && (currentNode->x != endX || currentNode->y != endY))
    {
        astarPathCount = 0;
        return false;
    }
    else
    {
        while (currentNode != NULL)
        {
            CCPoint tilePoint;
            tilePoint.x = currentNode->x;
            tilePoint.y = currentNode->y;
            
            CCTMXLayer* mapLayer = tiledMap->layerNamed("mainCityLayer");
            CCSprite* tile = mapLayer->tileAt(ccp(tilePoint.x, tilePoint.y));
            astarPathList.push_front(tilePoint);
            currentNode = currentNode->father;
            astarPathCount++;
        }

        return true;
    }

    deleteAstar(astar);
    return false;
}


[此贴子已经被作者于2021-1-10 09:53编辑过]

搜索更多相关主题的帖子: NULL int head return next 
2021-01-04 18:56



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-504526-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.026651 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved