我正在为一个课程组建一个项目,要求我将AI放在Flash AS3中的自上而下的战术策略游戏中。
我决定使用基于节点的路径查找方法,因为游戏基于圆形运动方案。当玩家移动一个单位时,他基本上绘制了一系列连接玩家单位将跟随的线段。
我试图通过创建一个遍历目标节点的节点列表,为我们游戏中的AI单元组合一个类似的操作。因此我使用了Astar(生成的路径可用于创建此行)。
这是我的算法
function findShortestPath (startN:node, goalN:node)
{
var openSet:Array = new Array();
var closedSet:Array = new Array();
var pathFound:Boolean = false;
startN.g_score = 0;
startN.h_score = distFunction(startN,goalN);
startN.f_score = startN.h_score;
startN.fromNode = null;
openSet.push (startN);
var i:int = 0
for(i= 0; i< nodeArray.length; i++)
{
for(var j:int =0; j<nodeArray[0].length; j++)
{
if(!nodeArray[i][j].isPathable)
{
closedSet.push(nodeArray[i][j]);
}
}
}
while (openSet.length != 0)
{
var cNode:node = openSet.shift();
if (cNode == goalN)
{
resolvePath (cNode);
return true;
}
closedSet.push (cNode);
for (i= 0; i < cNode.dirArray.length; i++)
{
var neighborNode:node = cNode.nodeArray[cNode.dirArray[i]];
if (!(closedSet.indexOf(neighborNode) == -1))
{
continue;
}
neighborNode.fromNode = cNode;
var tenativeg_score:Number = cNode.gscore + distFunction(neighborNode.fromNode,neighborNode);
if (openSet.indexOf(neighborNode) == -1)
{
neighborNode.g_score = neighborNode.fromNode.g_score + distFunction(neighborNode,cNode);
if (cNode.dirArray[i] >= 4)
{
neighborNode.g_score -= 4;
}
neighborNode.h_score=distFunction(neighborNode,goalN);
neighborNode.f_score=neighborNode.g_score+neighborNode.h_score;
insertIntoPQ (neighborNode, openSet);
//trace(" F Score of neighbor: " + neighborNode.f_score + " H score of Neighbor: " + neighborNode.h_score + " G_score or neighbor: " +neighborNode.g_score);
}
else if (tenativeg_score <= neighborNode.g_score)
{
neighborNode.fromNode=cNode;
neighborNode.g_score=cNode.g_score+distFunction(neighborNode,cNode);
if (cNode.dirArray[i]>=4)
{
neighborNode.g_score-=4;
}
neighborNode.f_score=neighborNode.g_score+neighborNode.h_score;
openSet.splice (openSet.indexOf(neighborNode),1);
//trace(" F Score of neighbor: " + neighborNode.f_score + " H score of Neighbor: " + neighborNode.h_score + " G_score or neighbor: " +neighborNode.g_score);
insertIntoPQ (neighborNode, openSet);
}
}
}
trace ("fail");
return false;
}
现在这个函数创建的路径通常不是最优的或者在给定目标时完全不准确,这通常发生在我有不可路径的节点时,我现在不太确定我做错了什么。
如果有人可以帮我纠正这一点,我会非常感激。
一些笔记
我的OpenSet本质上是一个优先级队列,因此我按成本对节点进行排序。 这是函数
function insertIntoPQ (iNode:node, pq:Array)
{
var inserted:Boolean=true;
var iterater:int=0;
while (inserted)
{
if (iterater==pq.length)
{
pq.push (iNode);
inserted=false;
}
else if (pq[iterater].f_score >= iNode.f_score)
{
pq.splice (iterater,0,iNode);
inserted=false;
}
++iterater;
}
}
谢谢!
答案 0 :(得分:2)
你能解释一下这些界限的目的是什么:
if (cNode.dirArray[i] >= 4)
{
neighborNode.g_score -= 4;
}
A *适用于成本总是正的问题,即路径成本单调增加。
关于最优性,要检查的另一件事是,distFunction()总是返回一个小于或等于达到目标的实际成本的值(即启发式被要求允许,因此A *可以保证它将找到最佳解决方案)。
我对AS3一无所知 - 所以我无法评论优先级队列的使用情况。
答案 1 :(得分:1)
这里有一个快速实施:https://github.com/tomnewton/AS3AStar
答案 2 :(得分:1)
试用http://script3.blogspot.com/2010/04/star-path-finding-algorthim-in.html 你可以在那里找到功能强大的* pathfinding类,带有平滑的寻路选项。