A*寻路算法
A*寻路算是游戏开发中很常见的一种寻路算法,网络上相关的介绍也非常多,这次从其他寻路算法谈起,来看一看A星算法是如何诞生的,本文所有寻路算法使用TypeScript实现
算法默认权重不为负数
广度优先搜索
广度优先搜索,就如同洪水一样,从搜索起点不断往外扩张
搜索实现
- 构建一个搜索队列searchList,列表中的节点就是等待搜索的节点,初始化时将起点加入到列表中; 构建一个searchRecord记录被搜索过的节点
- 从searchList搜索队列中取出一个节点,获取到该节点的临近节点(这里取上下左右4个节点),若临近节点没有被搜索过,将临近节点加入到searchList中
- 重复步骤2,直到搜索完所有节点
提前结束
上面的搜索步骤是地图中所有节点进行遍历,实际上寻路都存在一个或多个目标,当搜索到目标就可以停止算法,避免不必要的查询
关于searchRecord
serachRecord用来记录搜索过的节点,当寻找到最终目标,最终的搜索路径就通过serachRecord构建出来, 我这里使用的是一个Dictionay来实现的,key是由节点的xy值构成的一个字符串,以表示一个唯一的节点,
比如,当我们以(5,5)为起点,[(4, 5), (5, 4), (5, 6), (6, 5)]这四个点将会被搜索,那么searchReocrd的结构就是这样的
searchRecord = {
'4_5': Node(5, 5),
'5_4': Node(5, 5),
'5_6': Node(5, 5),
'6_5': Node(5, 5)
}
这样的结构表明了key与value的父子关系: (5, 5) -> (4, 5), 当搜索继续下去,可能会出现下面的结果
searchRecord = {
'4_5': Node(5, 5),
'3_5': Node(4, 5),
'2_5': Node(3, 5),
'1_5': Node(2, 5),
......
}
假如(1, 5)是我们的终点,那么根据searchRecord我们可以轻松构建出最终的搜索路径: (5, 5) -> (4, 5) -> (3, 5) -> (2, 5) -> (1, 5)
核心代码实现
let searchQueue: Array<Node> = [star