群聚AI

群聚,就是多个非玩家角色一起行动,而不是个别行动。比如说:你看到的是一群大雁,它们的飞行是有一定的规律,而且你完全可以看出来它们会排成一字或者人字,不会是乱糟糟的飞行。那么,我们在游戏中,诸如巡逻小队之类的移动又是什么样的呢?

 

1987年,Craig Reynolds发表了一篇名为《Flocks,Herds and Schools: A Distributed Behavial Model》的论文,在这篇论文中,他提出了基本的群聚算法模型,甚至可以这样说,后续的一系列群聚算法都有这篇论文的身影。

 

那么我们来看看Craig Reynolds提到的boids——类鸟群的模拟群体。在这种类鸟群里面, 是没有领导核心,它们都是跟着群体在走,而这个群体似乎是自己有自己的想法。

 

初看起来,这种算法一定非常的复杂,但是,我们不得不说,真正的惊讶来自于其后的规则,总共描述这样的行为仅仅只有优雅而简单的三条规则。

 

凝聚:每个单位都往其临近单位的平均位置行动。

对齐:每个单位行动时,都要把自己对齐在其临近单位的平均方向上。

分隔:每个单位行动时,要避免撞上其临近单位。

 

为了分析我们这个群聚系统,我们需要理解一些基本的概念:

1,  单位的视野,我们以r为单位的视野半径,以θ为视野角度,落在这个圆弧内的所有物体都是可见的。

2,  避开规则(Avoidance rule),单位不会被彼此撞上。

3,  凝聚规则,单位离得太远就应该靠近一点,这个规则和避开规则合在一起,从而形成了群聚。

 

我们来看看一个实际的例子:

void DoUnitAI(int i)

{

       int j;

       int N;//临近单位数量

       Vector Pave;//平均位置向量

       Vector Vave;//平均速度向量

       Vector Fs;//总净转向力

       Vector Pfs;//Fs施加的位置

       Vector d,u,v,w;

       double m;

       bool InView;

       bool DoFlock = WideView||LimitedView||NarrowView;

       int RadiusFactor;

 

       //初始化

       Fs.x = Fs.y = Fs.z = 0;

       Pave.x = Pave.y = Pave.z = 0;

       Vave.x = Vave.y = Vave.z = 0;

       N = 0;

       Pfs.x = 0;

       Pfs.y = Units[i].fLength/2.0f;

       …

       …

}

 

这个函数里面还有关于临近单位相关信息处理:

for (j = 1; j < _MAX_NUM_UNITS; j++)

{

       if (i != j)

{

       InView = false;

       d = Units[j].vPositon – Units[i].vPosition;

       w = VRotate2D(-Units[i].fOrientation, d);

       if (WideView)

       {

              InView = ((w.y > 0)

|| ((w.y < 0)

&& (fabs(w.x) > fabs(w.y) * _BACK_VIEW_ANGLE_FACOTOR)));

                     RadiusFactor = _WIDEVIEW_RADIUS_FACTOR;

       }

       if (LimitedView)

       {

              InView = (w.y > 0);

              RadiusFactor = _LIMITEDVIEW_RADIUS_FACTOR;

       }

       if (NarrowView)

       {

              InView = (((w.y > 0) && (fabs(w.x) <

fabs(w.y) * _FRONT_VIEW_ANGLE_FACTOR)));

                     RadiusFactor = _NARROWVIEW_RADIUS_FACTOR;

       }

       if (InView)

       {

              if  (d.Magnitude() <= (Units[i].fLength * RadiusFactor))

              {

                     Pave += Units[j].vPosition;

                     Vave += Units[j].vVelocity;

                     N++;

              }

       }

       …

       …

}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值