AStar算法(大物件寻路)

本文讲述了如何对传统的A*算法进行改造,以适应大物件寻路问题,如22格子地图,涉及到F值计算、开放列表和封闭列表的使用,以及中心点和周围点的处理。作者提供了详细步骤和示例代码,包括检查目标点和路径打印的方法。
摘要由CSDN通过智能技术生成

前言

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格子物件
地图为30
30 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工程
有需要再上传
如果觉得有用,麻烦点个赞,加个收藏

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值