但也花了我半天的时间修改它的bug,下面贴出劈人修改后的代码,节省大家的时间-直接copy它就行了.
//
// AstarItem.h
// AstarAlgorithm
//
// Created by liboxiang on 13-5-21.
//
//
#ifndef __AstarAlgorithm__AstarItem__
#define __AstarAlgorithm__AstarItem__
#include <iostream>
#include "cocos2d.h"
class AstarItem: public cocos2d::CCObject
{
public:
// AstarItem();
// ~AstarItem();
// 行 / 列 setter/getter
void setPos(const int &col, const int &row)
{
id_col = col;
id_row = row;
}
int getCol(){return id_col;}
int getRow(){return id_row;}
//实际估价 setter/getter
void setG(const int &g){id_g = g;}
int getG(){return id_g;}
//估计代价 setter/getter
void setH(const int &h){id_h = h;}
int getH(){return id_h;}
//父节点 setter/getter
void setFid(const int &fid){id_fid = fid;}
int getFid(){return id_fid;}
//估价函数 setter/getter
void setF(const int &f){id_f = f;}
int getF(){return id_f;}
private:
int id_col;//列
int id_row;//行
int id_g;//实际估价
int id_h;//估计代价
int id_fid;//父节点 标志close中的index
int id_f;//估价函数 f = g + h
};
#endif
//
// Astar.h
// AstarAlgorithm
//
// Created by liboxiang on 13-5-21.
//
//
#ifndef __AstarAlgorithm__Astar__
#define __AstarAlgorithm__Astar__
#include <iostream>
namespace cocos2d
{
class CCArray;
class CCTMXTiledMap;
}
class Astar
{
private:
int curCol, curRow, aimCol, aimRow;
// int AimX, AimY, AimW, AimH;
cocos2d::CCArray *open;
cocos2d::CCArray *close;
cocos2d::CCArray *path;
cocos2d::CCTMXTiledMap *map;
std::string conflictProerty;
int conflictValue;
int getG(const int &col, const int &row, const int &id);//获得g()
int getH(const int &col, const int &row);//获得h()
void fromOpenToClose();//将open中的元素导入close
void removeFromOpen();//从open列表中删除元素
void getPath();//获得整个路径
void starSearch(const int &fid);//搜索
void resetSort(int last);//排序
bool checkClose(const int &col, const int &row);//检查close
void addToOpen(const int &col, const int &row, const int &id);//向open添加元素
bool checkMap(const int &col, const int &row);//检查地图
bool checkOpen(const int &col, const int &row, const int &id);//检查列表
public:
Astar();
~Astar();
cocos2d::CCArray *findPath(const int &curX,
const int &curY,
const int &aimX,
const int &aimY,
cocos2d::CCTMXTiledMap *passMap,
const std::string &theConflictProerty,
const int &theConflictValue);//入口函数
};
#endif
//
// Astar.cpp
// AstarAlgorithm
//
// Created by liboxiang on 13-5-21.
//
//
#include "Astar.h"
#include "cocos2d.h"
#include "AstarItem.h"
using namespace cocos2d;
Astar::Astar():map(NULL), conflictProerty("conflict"), conflictValue(1)
{
path = CCArray::create();
path->retain();
open = CCArray::create();
open->retain();
close = CCArray::create();
close->retain();
}
Astar::~Astar()
{
CC_SAFE_RELEASE(open);
CC_SAFE_RELEASE(close);
CC_SAFE_RELEASE(path);
CC_SAFE_RELEASE(map);
}
int Astar::getG(const int &col, const int &row, const int &id)//获得g()
{
AstarItem *closeMember = (AstarItem *)close->objectAtIndex(id);
int fx = closeMember->getCol();
int fy = closeMember->getRow();
int fg = closeMember->getG();
if (col - fx != 0 && row - fy != 0)
{
return fg + 14;
}
else
{
return fg + 10;
}
}
int Astar::getH(const int &col, const int &row)//获得h()
{
//获得该点的h值
return abs(aimCol - col) * 10 + abs(aimRow - row) * 10;
}
void Astar::fromOpenToClose()//将open中的元素导入close
{
//把open列表中的点 放到close列表
AstarItem *temp = (AstarItem *)open->objectAtIndex(1);
close->addObject(temp);
removeFromOpen();
}
void Astar::removeFromOpen()//从open列表中删除元素
{
//最後一个 替换第一个
open->replaceObjectAtIndex(1, open->lastObject(), true);
//删除最後一个
open->removeLastObject();
int last = open->count() - 1;
//对排序
int head = 1;
while ( (head * 2) <= last )
{
int child1 = head * 2;
int child2 = child1 + 1;
int childMin(0);
//找出 childMin
if (child2 <= last)
{
AstarItem *child1AstarItem = (AstarItem *)open->objectAtIndex(child1);
AstarItem *child2AstarItem = (AstarItem *)open->objectAtIndex(child2);
childMin = child1AstarItem->getF() < child2AstarItem->getF() ? child1 : child2;
}
else
{
childMin = child1;
}
//head > childMin就交换
AstarItem *headAstarItem = (AstarItem *)open->objectAtIndex(head);
AstarItem *childMinAstarItem = (AstarItem *)open->objectAtIndex(childMin);
if (headAstarItem->getF() <= childMinAstarItem->getF())
{
break;
}
open->exchangeObject(headAstarItem, childMinAstarItem);
head = childMin;
}
}
void Astar::getPath()//获得整个路径
{
path->addObject(close->lastObject());
while (true)
{
if (((AstarItem *)path->objectAtIndex(0))->getG() == 0 )
{ //达到终点时,结束循环
break;
}
path->insertObject(
close->objectAtIndex(((AstarItem *)path->objectAtIndex(0))->getFid()),
0);
}
curCol = aimCol;
curRow = aimRow;
}
void Astar::starSearch(const int &fid)//搜索
{
AstarItem *fidAstarItem = (AstarItem *)close->objectAtIndex(fid);
//view coordinate
int col = fidAstarItem->getCol();
int row = fidAstarItem->getRow();
//搜索目前点的上 左 下 右 四个方向
//上
int myCol = col;
int myRow = row - 1;
if (myRow >= 0 && checkMap(myCol, myRow))
{
if (checkOpen(myCol, myRow, fid) && checkClose(myCol, myRow))
{
addToOpen(myCol, myRow, fid);
}
}
//--上左
myCol = col -1;
myRow = row - 1;
if (myCol >= 0 && myRow >= 0 && checkMap(myCol, myRow))
{
if (checkOpen(myCol, myRow, fid) && checkClose(myCol, myRow))
{
addToOpen(myCol, myRow, fid);
}
}
//左
myCol = col - 1;
myRow = row;
if (myCol >= 0 && checkMap(myCol, myRow))
{
if (checkOpen(myCol, myRow, fid) && checkClose(myCol, myRow))
{
addToOpen(myCol, myRow, fid);
}
}
//--左下
myCol = col -1;
myRow = row + 1;
if (myCol >= 0 && myRow <= map->getMapSize().height && checkMap(myCol, myRow))
{
if (checkOpen(myCol, myRow, fid) && checkClose(myCol, myRow))
{
addToOpen(myCol, myRow, fid);
}
}
//下
myCol = col;
myRow = row + 1;
if (myRow <= map->getMapSize().height && checkMap(myCol, myRow))
{
if (checkOpen(myCol, myRow, fid) && checkClose(myCol, myRow))
{
addToOpen(myCol, myRow, fid);
}
}
//--右下
myCol = col + 1;
myRow = row + 1;
if (myCol <=map->getMapSize().width && myRow <= map->getMapSize().height && checkMap(myCol, myRow))
{
if (checkOpen(myCol, myRow, fid) && checkClose(myCol, myRow))
{
addToOpen(myCol, myRow, fid);
}
}
//右
myCol = col + 1;
myRow = row;
if (myCol <=map->getMapSize().width && checkMap(myCol, myRow))
{
if (checkOpen(myCol, myRow, fid) && checkClose(myCol, myRow))
{
addToOpen(myCol, myRow, fid);
}
}
//--上右
myCol = col + 1;
myRow = row - 1;
if (myCol <=map->getMapSize().width && myRow >= 0 && checkMap(myCol, myRow))
{
if (checkOpen(myCol, myRow, fid) && checkClose(myCol, myRow))
{
addToOpen(myCol, myRow, fid);
}
}
}
void Astar::resetSort(int last)//排序
{
while (last > 1)
{
int half = last / 2;
AstarItem *lastAstarItem = (AstarItem *)open->objectAtIndex(last);
AstarItem *halfAstarItem = (AstarItem *)open->objectAtIndex(half);
if (halfAstarItem->getF() <= lastAstarItem->getF()) break;
open->exchangeObject(halfAstarItem, lastAstarItem);
last = half;
}
}
bool Astar::checkClose(const int &col, const int &row)//检查close
{
AstarItem *closeMember = NULL;
CCObject *theObject = NULL;
CCARRAY_FOREACH_REVERSE(close, theObject)
{
closeMember = (AstarItem *)theObject;
if (closeMember->getCol() == col && closeMember->getRow() == row)
{
return false;
}
}
return true;
}
void Astar::addToOpen(const int &col, const int &row, const int &id)//向open添加元素
{
AstarItem *temp = new AstarItem();
temp->setPos(col, row);
temp->setFid(id);
int g = getG(col, row, id);
int h = getH(col, row);
temp->setG(g);
temp->setH(h);
temp->setF(g + h);
open->addObject(temp);
resetSort(open->count() - 1);
}
bool Astar::checkMap(const int &col, const int &row)//检查地图
{
CCTMXLayer *layer = map->layerNamed("grass");
CCAssert(layer, "grass layer is not found at Astar::checkMap");
if (col >= map->getMapSize().width || row >= map->getMapSize().height)
{
return false;
}
unsigned int tileGid = layer->tileGIDAt(ccp(col, row));CCAssert(tileGid > 0, "tileGid is empty");
CCDictionary *tileDic = map->propertiesForGID(tileGid);CCAssert(tileDic, "tileDic is not found at Astar::checkMap");
CCString *mValue = (CCString *)tileDic->objectForKey(conflictProerty.c_str());CCAssert(mValue, "mValue is not found at Astar::checkMap");
if (mValue->intValue() == conflictValue)
{
return false;
}
else
{
return true;
}
}
bool Astar::checkOpen(const int &col, const int &row, const int &id)//检查列表
{
AstarItem *openMember = NULL;
CCObject *theObject = NULL;
unsigned int index = open->count() - 1;
CCARRAY_FOREACH_REVERSE(open, theObject)
{
openMember = (AstarItem *)theObject;
if (openMember->getCol() == col && openMember->getRow() == row)
{
int tempG = getG(col, row, id);
if (tempG < openMember->getG())
{
openMember->setG(tempG);
openMember->setFid(id);
openMember->setF(openMember->getG() + openMember->getH());
resetSort(index);
}
return false;
}
--index;
}
return true;
}
CCArray *Astar::findPath(const int &curX,
const int &curY,
const int &aimX,
const int &aimY,
CCTMXTiledMap *passMap,
const std::string &theConflictProerty,
const int &theConflictValue)//入口函数
{
curCol = curX;
curRow = curY;
aimCol = aimX;
aimRow = aimY;
conflictProerty = theConflictProerty;
conflictValue = theConflictValue;
if (map != passMap)
{
CC_SAFE_RELEASE(map);
map = passMap;
map->retain();
}
path->removeAllObjects();
// index = 0;
AstarItem *temp = new AstarItem();
open->addObject(temp);
//index = 1;
AstarItem *temp1 = new AstarItem();
temp1->setPos(curCol, curRow);
temp1->setG(0);
int ag = getH(curCol, curRow);
temp1->setH(ag);
temp1->setFid(0);
temp1->setF(0 + ag);
open->addObject(temp1);
//遍历寻找路径
while (open->count() > 1)
{
//open 中 最小的移动啊 close
//open 中 重新排列
fromOpenToClose();
int fatherid = close->count() - 1;
AstarItem *lastAstarItem = (AstarItem *)close->objectAtIndex(fatherid);
if (abs(aimCol - lastAstarItem->getCol()) == 0 &&
abs(aimRow - lastAstarItem->getRow()) == 0)
{
getPath();
break;
}
else
{
//搜索
starSearch(fatherid);
}
}
open->removeAllObjects();
close->removeAllObjects();
//获得路径
if (path->count() == 0)
{
return NULL;
}
else
{
AstarItem *lastAstarItem = (AstarItem *)path->lastObject();
if (lastAstarItem->getCol() != aimCol ||
lastAstarItem->getRow() != aimRow)
{
AstarItem *temp = new AstarItem();
temp->setPos(aimCol, aimRow);
path->addObject(temp);
}
return path;
}
}