skip to main |skip to sidebar
显示标签为“AI”的博文。显示所有博文
显示标签为“AI”的博文。显示所有博文

2007-12-26

[AI]高级人工智能(2)——结合队伍

[AI]高级人工智能(1)——回避障碍物

结合队伍就是诱导各个人到周围的人的平均位置。这是队伍一起行动的三大步骤之一。通过结合,各个人就会聚合到一起,出现队伍。

效果:

人刚开始是随机移动,但遇到其他的人时,就会跟随他。但碰到障碍物等时有可能无法跟上,而又开始随机移动。当一群(boids)遇到另外一群时有可能结合在一起,也有可能队员发生互换后分开。

得到周围的人

每一个人有一个视野距离与视野范围。比如某个机器人可以看到 100m ,眼睛的夹角在120度 以内的物体。其中"100m"为视野距离(以下称为 r),"120度"为视野范围(以下称为 th)。

核心代码:

//周围的人列表。
internal var aroundList:Array;

//可视列表。
internal var inViewList:Array; //创建可视列表。
public function resetViewList():void {
inViewList = [];
aroundList = [];
for each(var u:C2Unit in onwer.unitsList) {
if(!u.following && u != this) {
if(inAround(u)) {
aroundList.push(u);
if(inView(u)) {
inViewList.push(u);
}
}
}
}
} //判断是否在周围。
public function inAround(u:C2Unit):Boolean {
if(Vector2d.distance(pos, u.pos) > VIEW_DISTANCE) {//VIEW_DISTANCE 为 r
return false;
}
return true;
}

//判断是否在视野范围内。
public function inView(u:C2Unit):Boolean {
var dsu:Vector2d = new Vector2d().sub(u.pos, pos);//dsu = u - pos (pos为自己的坐标)
if(dsu.angle2(pos)>VIEW_WIDTH) {//VIEW_WIDTH 为 th/2
return false;
}
return true;
}

结合

实现结合,其实很简单,就是把速度(方向和长度)设为周围的人的平均速度即可。

核心代码:

//结合。
internal function follow():void {
if(inViewList.length) {
var avg:Vector2d = new Vector2d();
for each(var u:C2Unit in inViewList) {
avg.addTo(u.v);
}
avg.scaleTo(1/inViewList.length);
v.reset(avg);
following = true;
}else{
following = false;
}
}

完整源码下载:结合队伍.rar,或访问我的附件

2007-12-23

[AI]高级人工智能(1)——回避障碍物

效果:

在连续动作环境(不是Tile Based 环境)中,回避障碍物是很复杂。因为不像 Tile Based 环境,"点"在理论上有无限多,很难准确地判断。

但不是没有办法的,回避障碍物可以使用 Lenard-Jones potential 函数

它的方程为:

[U = -A/pow(r,n) + B/pow(r,m)]

n、m 为不同常量时的曲线为:

[Graph]

Lenard-Jones potential 函数是物理中的一个函数,他表示分子间的引力与斥力的势能。U 为原子间的势能,它与原子间的距离 r 成反比。AB 就像 mn 一样,是常量,其中 -A/pow(r,n) 表示引力部分,B/pow(r,m) 表示斥力部分。在 r 很小时会产生斥力,当 r 很大时会产生引力。参数 mn 控制曲线的斜率,AB 控制力的强度。

如果在游戏中,把障碍物与人物看成原子的话,就可以使用 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

[AI for Game Developers]