矢量寻路算法-思路和源代码

来源:互联网 发布:360游戏优化器系统卡死 编辑:程序博客网 时间:2024/05/16 19:03

今年15,出于爱好很早就开始学编程了,第一次写博客,望大家多多关照。


大家都是计算机爱好者,可以加我个人的QQ交流:740382997

或者发邮件给我:yichensoft@126.com


同时我自己有一个翼尘软件工作室,大家有兴趣也可以加入,Q群号:252367359


首先声明一下本文所讲的矢量寻路是我原创的,甚至连一点资料都没查过,花了很多节数学课构思再用了一个下午写成的算法。

大家要转的话请贴上原帖地址http://blog.csdn.net/u011351840/article/details/9280705

本来以为自己是矢量寻路的首创者,后来看到这篇文章http://bbs.9ria.com/thread-102623-1-1.html才发现原来早已有了先例,不过我们的思路还是有区别的,那么下面就来说说我自己原创的矢量寻路算法。


矢量寻路的基本单位是Node,节点,所有单位都是由Node组成,每个Node都有nextNode和lastNode,也就是前节点和后节点,这样多个Node就可以组成一个循环链的结构,构成一个多边形,也就是矢量寻路中的障碍。


上图展示了多边形的构成,从一个节点出发可以查询到所有的节点,并且可以从next和last这两种方法查询。


了解了矢量世界的构成就能有个初步的寻路思路了,如图,从左边那个方块(实际应用上也就是主角,以下简称A)到右边的终点处(简称B)。中间有一个不规则的凹多边形障碍。


矢量寻路的最开始是查找多边形中分别距离起点A和终点B最近的一个节点,下图中两个蓝色的点就是分别离A和B最近的点


从离起点A最近的点(以下简称NA)出发,分别从next和last两个方向出发,过程中所有查询到的点都添加到集合类中,知直到查询到离终点B最近的点(简称NB),这样可以得到两条路,红色箭头指向的黄色路径和绿色箭头指向的绿色路径。


显然这两条路都太长了,最短的应该是这样


所以我们要对找到的路径进行优化,找到可行并且最短的路径。

对于黄色路径(以下简称WN)和绿色路径(简称WL)的优化方式是一样的,这里以WL为例。

把刚才找路所得的集合类拿出来,里面所有的节点组合成了一条可行但是很长的路。

优化开始

从集合类的末尾开始,也就是路的尽头,逐个查找,看看从这个点到A之间是否会有障碍物,此图显示最后一个点和A之间有障碍,不能通行,所以接着查找倒数第二个点。


直到一直查找到正数第二个点才发现,这个点和A点之间没有任何阻挡,可以直接通行,再实例化一个集合类,把这个点添加进去,这个集合类就是优化之后的路径


接下来再以刚才找到的,可以通行的,正数第二个点为起点,一样从路末开始,从后往前查找是否有点可以直接通行,直接得出终点和这个点之间没有阻挡,可以直接通行。


那么整个路径就被优化成了只有两个节点——正数第二个点和终点,而且可以通行,这样路径优化也完成了。

用这种方式对WL和WN进行优化,再计算出路径长度,也就是把集合类里面相邻的两个点的距离算出来,再把单独两点距离加起来就是路径的总长,从两条路中选择总长最小的,就完成了这次寻路。

这样的寻路即使是对于像上图一样很特别的凹多边形也可以完美地找到路径,接下来需要解决的就是面对多个多边形的寻路。


起点仍是A,把红点简称为B。

这次我们要化整为零,逐个击破,首先找到从A到B遇到的所有障碍,再以相对于起点的远近排个序,米黄色的这个障碍就是距离A最近的障碍,从他先下手。


用刚才对一个多边形进行寻路的方法,对这个米黄色障碍寻路,蓝灰色的障碍暂时无视,这样可以得出和刚才差不多的路径。

终点是钉死不动的,而主角是移动的(如果不是拿来做RPG之类游戏的,可以直接遍历路径中所有的节点,找到一个点,从这个点到B只与第二个多边形相交,以这个点为起点继续寻路)


当主角移动到一个特殊的节点,这个节点到B只与下一个多边形相交(如果超过两个那么其他的多边形先无视),这时候再用前面的方法对下一个多边形进行寻路,就可以完成整个寻路。


效果就是这样,这是从我的程序里截图出来的


对于两个多边形寻路


接下来贴一些重要的源代码。其中像isIntersect这种方法具体的实现就不提供了,Java中甚至都有原样的算法,不过在这里我做了很多改进以适应矢量寻路。

矢量寻路中的核心思想,以Node节点作为基础单位,包含nextNode和lastNode以及x、y的位置信息。

int x,y;Node nextNode=null;Node lastNode=null;public Node(int x,int y){this.x=x;this.y=y;}

多边形的构造,利用nextNode和lastNode制作出一个循环链的结构。

for(int i=0;i<nodeNumber;i++){if(i<nodeNumber-1){node[i].setNextNode(node[i+1]);}else{node[i].setNextNode(node[0]);}if(i>0){node[i].lastNode=node[i-1];}else{node[0].lastNode=node[nodeNumber-1];}}


很重要的一步,算法的起始,找到离起点最近的一个点作为路径的起点。找到离终点最近的点也是大同小异。

public Node findStart(Barrier b,Node start,Node end){Node ns=start;Node ne=end;Node n=b.getNode();double ds1=getDistance(ns,ne);for(int i=0;i<b.getNodeNumber();i++){double ds2=getDistance(start, n);if(ds2<ds1&&!b.isIntersect(start,n)){ds1=ds2;ns=n;}n=n.getNextNode();}return ns;}
从last开始寻路,从next寻路也近乎相同
public Way findLeft(Barrier b,Node start,Node end,Node ns,Node ne){Node n=ns;Way way=new Way();way.add(start);way.add(ns);for(int i=0;i<b.getNodeNumber();i++){if(ns==ne) break;if(n.getLastNode()!=ne&&n.getLastNode()!=null){way.add(n.getLastNode());n=n.getLastNode();}else{way.add(ne);break;}}return way;}
优化路径的算法,从尽头开始找到第一个能通行的路,反复之后得到最短的路径。

public Way optimizeWay(Way way,Map map){Way ow=new Way();Node t=way.getNode(0);ow.add(way.getNode(0));int k=0;for(int i=way.getNodeNumber()-1;i>k;--i){if(!map.isIntersect(t, way.getNode(i))){k=i;t=way.getNode(i);ow.add(way.getNode(i));i=way.getNodeNumber();}}return ow;}

关于矢量寻路的思想和源码到此就结束了,非常感谢各位能耐心把这篇文章看完,有什么不足之处或者错误的地方欢迎大家指出

联系QQ:740382997

群:252367359

邮箱:yichensoft@126.com

同时也希望大家记住翼尘,我们还在努力。

翼尘软件工作室

原创粉丝点击