A*算法基础

学习资料:《游戏编程精粹1》第三章


简介

   本文旨在A*算法的基础入门,带读者了解A*算法的大概,不做过于详尽的深入研究和具体实现。除了A*的基础,A*算法还有许多的更先进的发展,如基于A*的战术式寻径、超越A*算法、动态A*(D*)算法、超越A*:IDA*(迭代延伸A*)和边缘搜索等。   

   A*是一种在状态空间中进行搜索的算法,它主要是通过检查特定状态的相邻或邻接状态来搜索从起始状态到目标状态的最小代价路径。

   教学实例:15数码难题(15-puzzle)   

   本质:A*算法反复检查它已经看到但是还没搜索到的最优希望的位置。当搜索的位置是目标时,A*算法结束;否则会进一步的搜索记录这个位置的所有相邻位置。

   具体过程:跟踪记录2个状态表(未检查状态Close和已检查状态Open)。不断检查Open表并更新新的状态(相邻状态)加入Open表中,将检查过的加入Close表中,并更新Open表中相同状态最小的代价(如果有),直到找到目标或者Open表清空(无路径访问到目标)。每个状态记录前一个状态的信息(类似指针链表),找到目标时回溯该状态的前状态拼接成一条完整状态路径。

   PS:状态即移动的位置、朝向、速度等信息,大多数情况下位置即可满足要求,但有时基于速度和朝向进行规划路径会更令人满意。


   伪代码(C语言):

Open: priorityqueue of searchnode
Closed: list of searchnode
AStarsearch(location startLoc,location GoalLoc, agenttype Agent) {
    clear open and closed
    // initialize a start nodestartNode. Loc = startLocstartNode.costFromstart = 0
    startNode.CostToGoal = PathcostEstimate(startLoc,
        GoalLoc, Agent)
    startNode.Parent = null
    push startNode on Open
    //process the list until success or failure
    while open is not empty {
        pop Node from openl // Node has lowest Totalcost
        // if at a goal, we're done
        if (Node is a goal node)i
            construct a path backward from Node to startLocreturn success
        }else {
        for each successor NewNode of Node {
            NewCost = Node.CostFromstart + Traversecost(Node, NewNode, Agent)
                //ignore this node if exists and no improvement
                if (NewNode is in 0pen or closed) and
                (NewNode.CostFromStart <= NewCost) {
                    continue
                }else { //store the new or
                        //improved information
                    NewNode.Parent = Node
                    NewNode.costFromstart = NewCost
                    NewNode.CostToGoal = PathCostEstimate(NewNode.Loc, GoalLoc, Agent)
                    NewNode.Totalcost = NewNode.CostFromstart + NewNode.CostToGoal
                if (NewNode is in Closed) {
                    remove NewNode from closed
                }
                if (NewNode is in Open) {
                adjust NewNode's location in Open
                    }else {
                push NewNode onto Open
                }
        }// now done with Node
    }
    push Node onto C1osed
}
    return failurel // if no path found and open is empty
}

A*拓展


   游戏中的路径规划:

  1. 将位置平面进行分割成空间(划分空间方式:矩形栅格、四叉树、凸多边形、可见点、广义圆柱体);
  2. 设定-相邻状态;
  3. 设定-代价:行进的代价或惩罚(例如汽车消耗燃料);
  4. 设定-估值:从起点到目标点的直线路径*最小地形代价。
                         启发式代价信息:一个数学公式,一般是一个极值条件。具体问题具体分析,简而言之,当搜索到达目标代价值时,没必要再沿着这条路径搜索,此时停止该路径搜索,转而进行其他路径的尝试(提高搜索速度)  。     
            

   A*审美优化:


        1.直路径:加入额外的代价因子,可以从多条可选路径中选择较为满意、美观的线路。相同代价下的路径可能有多种,直路径能让运动变得美观(AI摇摆地抵达目的会看起来“蠢”)。
               矩形栅格:加入额外代价因子(与上一步不在同一条直线上的新移步处罚,合理的处罚值为给定方向正常代价的一半)
               多边形:路径计算后对其的直线性进行优化3.6
        2.平滑路径(美化寻路表现效果):Catmull-Rom插值算法。寻路过程中,AI会有许多急转弯(生硬的机器人),此时通过一个简单的图形学插值算法即可化直线为曲线,让AI移动更加自然。
        3.分级路径:
           在地图进行远距离寻路(花费时间过长,例如从一个国家到另一个国家),此时进行分级路径移动。导航器不需要计算整条路径后才开始移动,而是边移动边寻路,虽然不是最优解,却能做到近似解,最关键的是能显著减少搜索空间和最终计算路径时间。
           在不同的阶段进行寻径:先找大范围的路径,然后再在局部级别进行寻径。
           简而言之,将地图划分为较大的多个模块,目标点在数个模块之外的地点。此时可按照一定的距离(比划分的模块大)设定目标(比如从起点到目标点的直线路径),进行寻路,找到目标的最短路径后,进行局部级别寻径(当前所处模块离目标点最近的位置),然后按照局部寻径路线进行移动。此时按照局部级别寻径的位置再按照一定距离设定新目标,循环往复直到找到目标(与目标处于同一模块)。注意:每次移动到局部级别目标点后,将之前的模块的状态点移除(抛弃除此(移动到局部级别目标点的路径)之外的路径),类似“剪枝”。
           优化表现效果:
               为了避免计算局部路径时的停顿(寻径中)
               ①.有预料的进行大略计算
               ②.添加寻路指令下达后效果,如声音、动画效果等


   移动成群的AI:


        1.将路径请求排队,并且当个体被请求运行时才运动(实际效果还是不错的)
        2.选择群里中的一个个体作为领队,只为它寻找一条路径,其他个体跟随该目标前进即可(可能会变得非常复杂,如领队中途死掉、被减速等)
        3.flocking算法


   A*速度优化:


        搜索空间优化
        存储结构优化


   算法优化:


        1.启发式代价:估计从一个特殊节点到目标节点的实际代价(为寻路进行方向导航,提高效率)
        2.搜索空间分离寻径数据:将无用的寻径节点移除
        3.预分配最小存储量
        4.在主节点表内存储探索过的节点:将个性化的节点存入哈希表中,用于快速检索。
        5.优化Open表:作为优先队列进行排序,优先队列可以作为一个二分堆实现(可使用STL进行简单实现)。
        6.其他小技巧:如不搜索刚刚搜索过的节点、设计师对于搜索空间(场景)的优化


总结:数学、物理要学好

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值