前言
A星(物件大小为一格)寻路,都很熟悉了吧,网上源码一堆,随便抄;
这章需要讲述 大物件的A星寻路,何为大物件,就是 比如 物件 为4个格子;
这样,原来的A星 没法直接用了,必须得改装;
这里以22 格子为例 物件讲述 (上下左右 4个方向),33 4*4 等都一样
1:A星算法 核心
F = G + H
F 方块的总移动代价
G 开始点到当前方块的移动代价
H 当前方块到结束点的预估移动代价
2:计算步骤
首先将根节点放入队列中。
将根节点放入封闭列表
开始循环
从队列中找f值F值最小的节点current
如果找到目标,则结束搜寻并回传结果。
否则将它所有尚未检验过的所有相邻节点加入队列中(这里可以是4个方向或8个方向)
假如某邻近点既没有在开放列表或封闭列表里面,则计算出该邻近点的g值和h值,并设父节点为P,然后将其放入开放列表 消耗 横/竖10 斜14
gCost = current.gCost + GetDistance(current, neighbor);
hCost = GetDistance(end, neighbor);
直至没有节点可以访问.
3:大物件怎么计算
22格子物件
地图为3030 1遮挡 0 可走 5 开始点 9 目标点
开始点左小角的4个5(), 28 row 1 col 2col
29row 1col 2col
目标为右上角偏左 一个9
取中心点
22 每有中间,有的 ,假如 22 物件 格子坐标 为 00, 01, 10 ,11 那么中心点为0.5 0.5 小数不计算,所以都放大 10倍 ,就是 5 5
其他跟 一格的一行,
主要说下 不一样的
1> 查找某点的周围4个点时, 一格 (上下左右)很好理解,22 格 周围有8格点,33 有12点
2>如果目标点只有1格点,那么判定是 只有2*2物件 4格中任何一格在这格目标点上,就算找到目标了;
上代码
bool checkpoint(int newX, int newY, vector<vector<int>> &map,int mapXSize,int mapYSize) {
if (newX < 0 || newX >= mapXSize) {
return false;
}
if (newY < 0 || newY >= mapYSize) {
return false;
}
if (map[newX][newY] == 1) {
return false; // 不可达
}
return true;
}
list<PPoint> AStart::findAroundPoint4Half(PPoint curPoint, PPoint& endPoint) {
list<PPoint> around;
const int mapXSize = map.size();
const int mapYSize = map[0].size();
const int curx = curPoint->x;
const int cury = curPoint->y;
const int endxR = endPoint->x/10; //还原到真实
const int endyR = endPoint->y/10; //还原到真实
int newX = 0;
int newY = 0;
int rx = 0;
int ry = 0;
int count = 0;
//const int TOTAL_DIR = 4;
//const int directions[TOTAL_DIR][2] = { {1, 0}, {0, 1}, {-1, 0}, {0, -1} };
//const int movedircollection[TOTAL_DIR] = { DIR_X_ADD ,DIR_Y_ADD ,DIR_X_SUB ,DIR_Y_SUB };
//const int directionsHalf[TOTAL_DIR][2][2] = { {{5,5},{5,-5}}, {{5,5},{-5,5}} , {{-5,5},{-5,-5}} ,{{5,-5},{-5,-5}} };
for (int i = 0; i < TOTAL_DIR; i++) {
//
count = 0;
newX = curx + directions[i][0] * 10;
newY = cury + directions[i][1] * 10;
for (int j = 0; j < 2; j++) {
int newX_t = newX + directionsHalf[i][j][0]; //curx + directionsHalf[i][j][0] + directions[i][0]*10;
int newY_t = newY + directionsHalf[i][j][1];//cury + directionsHalf[i][j][1] + directions[i][1]*10;
rx = newX_t / 10;// +directions[i][0];
ry = newY_t / 10;// +directions[i][1];
if (rx == endxR && ry == endyR) {
around.clear();
PPoint newPoint = new Point(endPoint->x, endPoint->y);
around.push_back(newPoint);
return around;
}
if (!checkpoint(rx, ry, map, mapXSize, mapYSize)) {
break;
}
++count;
}
if (count > 1) {
PPoint newPoint = new Point(newX, newY);
around.push_back(newPoint);
}
}
return around;
}
开始位置,目标位置 修改
start->x = start->x * 10 + 5; //中间点
start->y = start->y * 10 + 5; //中间点
end->x = end->x * 10; //放大10倍
end->y = end->y * 10; //放大10倍
计算G H 的消耗时 也需要放大10倍
4:测试
路劲打印的 7 为路劲 2*2物件
大概寻路路劲如下:手动画的比较粗略
5:DEMO工程
有需要再上传
如果觉得有用,麻烦点个赞,加个收藏