(轉)不使用物理引擎實現防止羣聚行爲敵人扎堆

轉自:http://www.gameres.com/thread_256279_1_1.htmlhtml

GameRes發佈,文/paladin_t,轉載請註明GameRes和做者


追擊、羣聚是極經常使用到的敵人行爲模式。靠攏玩家位置的移動叫追擊;羣聚指一批敵人集體採用統一的行動,就像一羣羣沙丁魚同樣。羣聚敵人每每配合追擊來對玩家施加壓力,所以本文隱含用追擊配合作羣聚示例。

若是羣聚行爲的敵人沒有對羣體內其餘敵人的感知能力,將形成一種很奇葩的現象:扎堆。我見過不少遊戲能夠控制主角兜來兜去讓羣聚敵人集中到一堆,或者你不動他們本身就會走成一條直線。

<ignore_js_op>不使用物理引擎實現防止羣聚行爲敵人扎堆 ... 

這很煩人,玩家會認爲敵人很是傻,若是玩家要採起躲避敵人的策略,挑戰性的要素只剩下對走位的決策和移動速度的比拼。更噁心的是每每敵人比你挨着我我挨着你還要親密,甚至所有疊加集中到一個點上。

<ignore_js_op>不使用物理引擎實現防止羣聚行爲敵人扎堆 ... 

喂,這太蠢了點吧。這是最raw最simple的實現方式,誰都能想出來。

<ignore_js_op>不使用物理引擎實現防止羣聚行爲敵人扎堆 ... 
敵人始終單純的趨向主角(也許還會作出對主角移動預判的計算,但不在本文討論範疇內),在主角從a點移動到b點的過程當中敵人始終保持這樣的趨向性。

<ignore_js_op>不使用物理引擎實現防止羣聚行爲敵人扎堆 ... 

用彩色曲線對例圖中敵人的移動軌跡作描繪,也許是這個樣子:

<ignore_js_op>不使用物理引擎實現防止羣聚行爲敵人扎堆 ... 

<ignore_js_op>不使用物理引擎實現防止羣聚行爲敵人扎堆 ... 

看到了吧,敵人羣體的範圍愈來愈小了。作爲開發者兼玩家,這種prototype級別的作法會給我留下此遊戲完成度很低的印象。

物理引擎在現代遊戲中已經不是什麼稀奇物件了,無論3D遊戲仍是2D遊戲,都能找到物理機制和遊戲表達結合的很是好的例子,某些遊戲走的更遠,對物理機制利用的更深刻,物理就是這種遊戲的所有樂趣。若是你的遊戲中恰巧有一個能夠隨手拿來利用一下的物理引擎,也許你能夠用它來防止敵人們過於親密,好比給每一個敵人一個比渲染包圍體略大一些的防撞車碰撞體。

<ignore_js_op>不使用物理引擎實現防止羣聚行爲敵人扎堆 ... 

這看起來就像敵人間互相有了斥力場,酷!大功告成,萬事大吉!

你得認可凡是作遊戲鬼點子多的人才不會知足於把方案思考到能用就好的程度。我不是排斥使用物理引擎,相反我很是喜歡物理機制,我曾給個人首款App定製實現了一個物理引擎,效率良好,運轉穩定,最關鍵的是這個精簡版的物理引擎功能很少很多剛恰好知足個人需求,徹底不必用更加高大上的庫。對於防止羣聚行爲敵人扎堆這件事我不想用物理引擎也是由於:徹底不必用啊。某些RTS不一樣兵種間有搭配性玩法,須要不一樣兵種的密度均衡,若是用物理引擎反而很難作。詢問了幾個同行,彷佛不用物理引擎對這事都沒什麼轍,沒辦法,又得本身動手了。讓咱們來看看若是不使用物理引擎本身處理敵人間的「推搡」是怎樣的狀況。

<ignore_js_op>不使用物理引擎實現防止羣聚行爲敵人扎堆 ... 

若是有兩隻敵人,只須要作1次計算讓一隻跟另外一隻保持適當距離就好了;若是有3只敵人,須要作3次這樣的計算;若是有4只,須要算6次;若是有5只呢,要算10次……這種算法的複雜度是O(n(n-1)/2),可想而知敵人數量多了這將成爲CPU的災難。經驗告訴我,複雜度中有高達形如「n乘以n」這樣的因子的算法都是要不得的,須要想辦法優化或作折衷。

思考優化方案從現實切入吧,咱們每一個人都有在方陣隊伍裏齊步走的經歷,左右腳步調的統一依靠「一二一」口號和踏步聲音作同步數據源;在方陣中相對位置的固定不變咱們不須要也不可能經過獲取方陣中其餘全部人的位置信息作反饋調整,事實上咱們只是瞄着視線範圍內與咱們臨近的同窗來作模糊斷定的。先考慮某一隻敵人無論別的敵人同窗本身單獨行動的行爲:

<ignore_js_op>不使用物理引擎實現防止羣聚行爲敵人扎堆 ... 

這很容易,只須要朝着主角的位置奔去就好了,咱們不妨把例圖中優先計算行動的敵人1當成走方陣時的排頭同窗,他們只須要走好本身的就好了。

取敵人1和主角位置連線(長度爲R的)線段上某一點,(好比不妨定R爲線段長度的一半),從主角位置到這一點(以R爲半徑)作一個圓,好歹咱們能夠知道敵人羣體的總數量有幾隻,把這個圓平均劃分爲n份,每一隻都朝着相對應的劃分的端點襲去,嗯,也許還得給每隻敵人作些移動方向的微調;因爲敵人1距主角愈來愈近,R是愈來愈小的,這個圓也會愈來愈向主角收縮,因而咱們神奇的達成了敵人的這一套行爲:

1. 羣體移動趨勢一致統一
2. 個體間在圓收縮到很小以前不會靠的很是近

<ignore_js_op>不使用物理引擎實現防止羣聚行爲敵人扎堆 ... 

圓只須要劃分一次,某一隻敵人只須要知道本身是第幾號就能夠計算出速度向量,看,複雜度一降低低到了O(n),單次計算中的向量計算也銳減。

再引伸談一點點,羣聚敵人分紅若干堆怎樣實現呢,不妨這樣來看,每一堆算作一個彙集羣體應用上文算法,再把某一羣體看作一個總體,若干個這樣的羣體同理應用羣聚算法(或其餘行爲模式)。

<ignore_js_op>不使用物理引擎實現防止羣聚行爲敵人扎堆 ... 

本文算法代碼可在github獲取。


文/paladin_t做者微博git

相關文章
相關標籤/搜索