理解引导行为:路径跟踪

路径跟踪是游戏开发中一个经常出现的问题。此教程涵盖引导行为的路径跟踪,这里的路径是提前根据点和线预设好的。

       注意:虽然此教程是用AS3和Flash实现的,你也可以在其他语言开发环境下使用这些类似的技巧和概念。当然前提是需要有基本的数学向量的知识。

       介绍

       路径跟踪可以用多种方式实现。Reynolds原型就是使用线来实现的,这里需要严格的按照线来实现。

       根据不同情况,准确度要求不同。角色可以根据线路运动,但是只是做一个参照而不是严格按照轨道来运行。

       此教程的路径跟踪是Reynolds原型的简化实现。运行效果不错,但是严重依靠数学的向量投影计算。

       设定路径

       路径可以是线连接的点的集合。即使曲线也可以用来描述路径,点和线处理处理得到相同的结果要简单的多。

 

 1 public class Path
 2 {
 3 private var nodes :Vector.<Vector3D>;
 4 
 5 public function Path() {
 6 this.nodes = new Vector.<Vector3D>();
 7 }
 8 
 9 public function addNode(node :Vector3D) :void {
10 nodes.push(node);
11 }
12 
13 public function getNodes() :Vector.<Vector3D> {
14 return nodes;
15 }
16 }

 

 如果需要使用曲线,则可以将其简化为一些连接的点:

 

曲线和直线

       Path类将用来描述路径。一般来说此类包含一个点向量和一些处理列表的方法:

       每个路径中的点都是一个三维空间中点的表示方式,角色的位置也是如此。

逐个节点移动

       为了根据路径导航,角色从路线起始逐个节点移动直到到达路线末点。

       路径中的每个点都可以看做为一个对象,因此行为查看如下所示:

 

挨个点查看

       角色会不断查看当前点,直到到达为止,然后路径中下一个点作为当前点。正如前面的碰撞避免教程中所述,每个行为的力都是在游戏更新时重新计算,因此从一个节点到另一个节点是圆滑的。

       Character类需要两个额外的属性来引导导航过程:当前节点和路径跟踪的引用。

       类如下所示:

 

 1 public class Boid
 2 {
 3 public var path :Path;
 4 public var currentNode :int;
 5 (...)
 6 
 7 private function pathFollowing() :Vector3D {
 8 var target :Vector3D = null;
 9 
10 if (path != null) {
11 var nodes :Vector.<Vector3D> = path.getNodes();
12 
13 target = nodes[currentNode];
14 
15 if (distance(position, target) <= 10) {
16 currentNode += 1;
17 
18 if (currentNode >= nodes.length) {
19 currentNode = nodes.length - 1;
20 }
21 }
22 }
23 
24 return null;
25 }
26 
27 private function distance(a :Object, b :Object) :Number {
28 return Math.sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
29 }
30 (...)
31 }

 

pathFollowing()函数用来产生路径跟踪方向,当前是没有的,但是它还是会选择合适的目标。Path!=null测试角色是否跟踪任何路径。如果是的话,就用当前节点作为当前目标。

       如果当前点和角色位置之间的目标数少于10,意味着角色已经到达当前节点,如果上述成立则将currentNode增加一,表示角色将在路径中寻找下一个点。整个过程循环运行,知道路径里没有点为止。

       计算和添加方向

       促使角色在路径中不断寻找节点的是寻找力。pathFollwing()函数以及选择了合适的节点,现在需要返回促使角色前进的的节点:

       路径追踪后会计算方向,然后加到角色速度向量里:

 

 1 private function pathFollowing() :Vector3D {
 2 var target :Vector3D = null;
 3 
 4 if (path != null) {
 5 var nodes :Vector.<Vector3D> = path.getNodes();
 6 
 7 target = nodes[currentNode];
 8 
 9 if (distance(position, target) <= 10) {
10 currentNode += 1;
11 
12 if (currentNode >= nodes.length) {
13 currentNode = nodes.length - 1;
14 }
15 }
16 }
17 
18 return target != null ? seek(target) : new Vector3D();
19 }

 

路径引导方向跟追寻行为类似,角色不断根据目标调整方向。不同之处在于角色是在寻找一个不动的目标,这样就可以在角色逐渐靠近的时候忽略另一个。

       结果如下:

 

1 steering = nothing(); // the null vector, meaning "zero force magnitude"
2 steering = steering + pathFollowing();
3 
4 steering = truncate (steering, max_force)
5 steering = steering / mass
6 
7 velocity = truncate (velocity + steering, max_speed)
8 position = position + velocity

 

实际中的路径跟踪。点击来查看方向。

       柔化轨迹

       当前的实现需要所有角色接触路径中的点来选择下一个目标。因此角色可能执非预期的动作模式,例如围绕一个点圆周运动直到到达。

       实际中,每个运动都遵循最优原则。例如一个人不可能总是在走廊中间行走。如果是一个拐弯,那么人会不断靠近墙,然后拐弯来缩短距离。

       上述的模式可以通过在路径中添加半径来不断重复。将半径应用到点,就可以看到路径的宽。这样就可以控制角色不断沿着路径走。

 

半径对路径跟踪的影响

       如果角色和点之间的距离小于等于半径,那表示已经到达点。这样就可以根据线和点来做引导。

       利用半径进行路径跟踪。点击Force按钮来查看方向,点击+跟-按钮来动态调整半径尺寸。

       半径越大,路径越宽,角色拐弯的距离也就越大。半径的值可以用来产生不同的追踪模式。

       前进和后退

       有时候需要让角色不断移动,直到到达路径末尾。例如在巡逻模式中,角色需要在到达末尾后返回起点,追踪相同的点。

       我们可以在character类里添加pathDir属性。此属性是一个整型值,用来控制角色沿着路径的方向。如果pathDir是1,则表示向路径末尾运动,-1表示向起始点运动。

       pathFollowing()函数做如下改动:

 

 1 private function pathFollowing() :Vector3D {
 2 var target :Vector3D = null;
 3 
 4 if (path != null) {
 5 var nodes :Vector.<Vector3D> = path.getNodes();
 6 
 7 target = nodes[currentNode];
 8 
 9 if (distance(position, target) <= path.radius) {
10 currentNode += pathDir;
11 
12 if (currentNode >= nodes.length || currentNode < 0) {
13 pathDir *= -1;
14 currentNode += pathDir;
15 }
16 }
17 }
18 
19 return target != null ? seek(target) : new Vector3D();
20 }

 

跟之前版本不同,此处的pathDir添加到currentNode属性里。这样就允许角色选择基于当前位置的路径的下一个点了。

       然后通过一个测试来检测角色是否到达路径末尾。如果到达,就将pathDir乘以-1,也就是取相反值,来让角色反方向行走。

       结果是一个不断来回运动的模式:

       上述是利用半径的来回路径追踪模式。点击Force按钮来显示方向,点击+或者-来动态调整半径尺寸。

       总结

路径追踪行为运行任何角色按照预先设定好的路径运动。路径是根据点来指引,可以调宽窄,产生不同运动模式来更贴近现实。

此教程中涵盖的实现时给予Reynolds提出的路径追踪行为原型的,但是还是获得良好的效果。

 

原文链接:理解引导行为:路径跟踪

 

原文链接:http://gamedev.tutsplus.com/tutorials/implementation/understanding-steering-behaviors-path-following/

 

 

 

 

 

posted @ 2013-07-10 13:12  【Winco】  阅读(1322)  评论(0编辑  收藏  举报