書中提到的群聚行為其實很單純且基本

來自於1987年SIGGRAPH論文,由Craig Reynolds發表的

『 Flocks, Herds, and Schools: A Distributed Behavioral Model 』

其行為主要是模擬鳥類及魚群的移動方式

基本原理一共有三點:

1. 凝聚(Cohesion):每個AI都會往鄰近AI的平均位置移動

cohesion.gif

2. 對齊(Alignment):每個AI移動時,會自動對齊鄰近AI的平均移動方向

alignment.gif

3. 分隔(Separation):每個AI移動時,需要避開撞倒鄰近AI

separation.gif

有點難以置信的,只需要以上三點即可做到群聚行為

再加上兩個元素,加強AI的群聚與追蹤行為

4. 閃避(Avoidance):每個AI移動時,會避開場景上的障礙物

5. 追蹤(Chase/Intercept):即之前提過的攔截模式 + 追蹤

 

首先,所有的AI都需要一個或數個扇形的Sensor

來偵測『可見的』AI及障礙物

neighborhood.gif

所謂可見度,就是指扇形角度以及半徑大小的意思

它也直接影響到AI群聚隊伍的『形狀』

接下來一邊移動一邊Sensor周遭的AI或障礙物

並通通把偵測到的東西都放進一個List裡面

以作為判斷下一個移動方向的依據

根據基本原理的凝聚,對齊與分隔

每次Update都會得到三個力量

這三個力量綜合即是你下一次要移動的方向

1. 凝聚(Cohesion):即Sensor到所有AI的平均位置,會得到一個點AvgPos,再得出你現在位置SelfPos與該點的相對向量AvgDirection = Vector(AvgPos - SelfPos)

2. 對齊(Alignment):這裡是取Sensor到所有AI的目前速度加總值,會得到一個合成力,Normalize後成為平均速度向量AvgVelocity

算出前兩個向量後,接下來要轉換成力量

也就是改變目前方向的力量,請見以下簡易function:

float GetDeflectForce(const NxVec3 &vMyDir, const NxVec3 &vTargetDir)
{
    float fDot = vMyDir.dot(vTargetDir);
    float fRadian = ConvertToRadians(fDot);
    if (vTargetDir.dot(this->GetRightVector()) < 0.0f)
        fRadian = -fRadian;

    return fRadian;
}

3. 分隔(Separation) + 4. 閃避(Avoidance):我把這兩部份合在一起算,因為看起來差不多

即是把Sensor到所有AI加上障礙物逐一與自己目前位置比較

會得到每一個相對的距離Dist,再除以Sensor的半徑Radius,會得到一個FactorForce

把以上所有的力量加總即是AI的偏移力量,同樣見以下function

float GetAvoidForce()
{
    for (it=m_lTooCloseAcotrList.begin();it!=m_lTooCloseAcotrList.end();it++)
    {
        pActor = *it;
        vDir = pActor->getGlobalPosition() - m_pActor->getGlobalPosition();
        fForce += vDir.length() / DETECT_BLOCK_RADIUS;
    }
    return fForce;
}
以物理學來說,就是旋轉角速度囉

 

到此為止,群聚的行為就已經出現了

但是群龍無首,感覺群聚行為很鬆散

此時Sensor內是空的AI,即沒有群聚行為的AI成為領導者

由它來指揮其他AI前進

於是我加了一個可控制的AI,讓領導的AI追蹤它

5. 追蹤(Chase/Intercept):攔截的部分上一篇文章已經講很多了

但有一點不一樣的是,最後算出來的預測攔截點要轉換成旋轉力量

於是再度把攔截點TargetPos,求出你現在位置SelfPos與該點的相對向量TargetDirection = Vector(TargetPos- SelfPos)

套用剛剛用到的GetDeflectForce()即可求得旋轉力

 

加上一點小變化

攔截模式的行為是預測,但所有AI都同樣行為未免太過呆板

於是領導的AI可選擇使用另一種追蹤:直接往目標物的位置移動

當然在這裡也需要轉換成為旋轉力量

最後就會看到兩支隊伍在追蹤

且一支隊伍是直接朝目標移動

另一支則是預測目標的行進方向,進而從中攔截

tracing.gif

 

經過測試之後雖不甚滿意但勉強可以接受

可以看得出來群聚以及追蹤行為

畢竟我也不想花太多時間去修正細部行為...

這個Demo有它致命的缺點在

即,它對障礙物的真測試有限的

當碰到一片長城,AI是有可能會被卡死的

這時候就會顯的很笨....

但基本上以群聚行為來說

這樣結果算是合格了

 

圖片來源:http://www.red3d.com/cwr/boids/

參考資料來源:http://examples.oreilly.com/ai/

P.S 由於沒有上傳空間加上Demo也沒做多好,So有需要的人直接跟我要吧~

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 kgsprogrammer 的頭像
    kgsprogrammer

    太陽系後援會

    seeulin 發表在 痞客邦 留言(0) 人氣()