效果:
在连续动作环境(不是Tile Based 环境)中,回避障碍物是很复杂。因为不像 Tile Based 环境,"点"在理论上有无限多,很难准确地判断。
但不是没有办法的,回避障碍物可以使用 Lenard-Jones potential 函数。
它的方程为:
n、m 为不同常量时的曲线为:
Lenard-Jones potential 函数是物理中的一个函数,他表示分子间的引力与斥力的势能。U 为原子间的势能,它与原子间的距离 r 成反比。A
、B
就像 m
、n
一样,是常量,其中 -A/pow(r,n)
表示引力部分,B/pow(r,m)
表示斥力部分。在 r
很小时会产生斥力,当 r
很大时会产生引力。参数 m
、n
控制曲线的斜率,A
、B
控制力的强度。
如果在游戏中,把障碍物与人物看成原子的话,就可以使用 Lenard-Jones potential 函数来实现回避障碍物。当十分接近时,会产生很大的斥力,再把 A
设为0
,使引力始终为0
这样回避障碍物就实现了。
核心代码:
var vo:Vector2d = new Vector2d();//障碍物的坐标
var vp:Vector2d = new Vector2d().reset(player);//人物的坐标
var r:Vector2d = new Vector2d();//人物与障碍物的差
var u:Vector2d = new Vector2d();
var dv:Vector2d = new Vector2d();
var B:Number = 20;//函数的 B 常量
for each(var i:Obstacle in obstaclesList) {
vo.reset(i);//vo = (i.x, i.y)
r.sub(vp, vo);//r = vp - vo
if(r.length >40) {//当 距离>40 时不判断,直接返回。
continue;
}
u.reset(r);//u = r
u.normalize();//把 u 设为单位向量
var d:Number = r.length/i.r;//d = |r| / i.r (i.r为障碍物的半径)
var U:Number = B/Math.pow(d,2.5);//A = 0,n = 1,m = 2.5
u.scaleTo(U);//u *= U
dv.add(player.v, u);//dv = player.v + u (player.v为人物的速度)
dv.length = 5//|dv| = 5
player.v.reset(dv);//player.v = dv
}
源码下载:AI_Avoid.rar。
参考文献:AI for Game Developers
没有评论:
发表评论