全部文章搬運自個人我的主頁:sheilasun.mehtml
去年風靡微信朋友圈的小遊戲「圍住神經貓」,我也試着作了一下,能夠戳這裏試玩→圍住神經貓。遊戲是用Egret引擎開發的,由於Egret是用Typescript語言構建的,所以這裏遊戲也是用Typescript來開發的。git
完整的代碼能夠戳個人Github→sheila1227/HTML5-GAME-shenjingcatgithub
點擊畫面上的灰色格子,慢慢將神經貓圍起來抓住。若是貓到達遊戲區邊緣則遊戲失敗。json
在網上搜索「圍住神經貓」遊戲,打開一個,並打開調試界面,從network中或者resource中把貓、灰色圓圈、橙色圓圈等圖片扒下來保存到本地。
須要注意的是,Egret新的MovieCilp架構設計以及MovieClip數據格式標準都與早期有些不一樣,我從網上扒下來的已經不適用了,根據新的數據格式標準作修改後mc的json文件以下:數組
{"mc":{ "stay":{ "frameRate":20, "labels":[], "frames":[ {"res":"stay0000","x":0,"y":0}, {"res":"stay0001","x":0,"y":0}, {"res":"stay0002","x":0,"y":0}, {"res":"stay0003","x":0,"y":0}, {"res":"stay0004","x":0,"y":0}, {"res":"stay0005","x":0,"y":0}, {"res":"stay0006","x":0,"y":0}, {"res":"stay0007","x":0,"y":0}, {"res":"stay0008","x":0,"y":0}, {"res":"stay0009","x":0,"y":0}, {"res":"stay0010","x":0,"y":0}, {"res":"stay0011","x":0,"y":0}, {"res":"stay0012","x":0,"y":0}, {"res":"stay0013","x":0,"y":0}, {"res":"stay0014","x":0,"y":0}, {"res":"stay0015","x":0,"y":0} ] }}, "res":{ "stay0000": {"x":0,"y":0,"w":61,"h":93}, "stay0001": {"x":61,"y":0,"w":61,"h":93}, "stay0002": {"x":122,"y":0,"w":61,"h":93}, "stay0003": {"x":183,"y":0,"w":61,"h":93}, "stay0004": {"x":0,"y":93,"w":61,"h":93}, "stay0005": {"x":61,"y":93,"w":61,"h":93}, "stay0006": {"x":122,"y":93,"w":61,"h":93}, "stay0007": {"x":183,"y":93,"w":61,"h":93}, "stay0008": {"x":0,"y":186,"w":61,"h":93}, "stay0009": {"x":61,"y":186,"w":61,"h":93}, "stay0010": {"x":122,"y":186,"w":61,"h":93}, "stay0011": {"x":183,"y":186,"w":61,"h":93}, "stay0012": {"x":0,"y":279,"w":61,"h":93}, "stay0013": {"x":61,"y":279,"w":61,"h":93}, "stay0014": {"x":122,"y":279,"w":61,"h":93}, "stay0015": {"x":183,"y":279,"w":61,"h":93} }}
主要總結下我在開發過程當中遇到的主要的兩個難題。微信
在這個遊戲中,每一個圓圈均可能有三種狀態架構
每當點擊了灰色圓圈,就會將其變成橙色圓圈即路障狀態,同時貓會緊跟着點擊的動做也向周邊走一步。app
遊戲區由9*9個圓圈組成,偶數行縮進圓圈半徑大小的寬度,這樣的佈局致使,貓理論上能夠有6個行走方向(每次只能走一步),分別是左,左上,右上,右,右下,左下,如這些位置上的圓圈爲路障狀態,則相應方向不可通行。
若是這六個方向的鄰居有五個都爲路障,那固然很好選擇線路,剩下的那個就是惟一的出路了,可是顯然狀況不可能如此簡單。咱們遇到的更多的狀況是,六個方向的鄰居上,有直接爲路障狀態的(那天然絕對不走這一步),有是可通行狀態的,可是彼此向邊緣的可達性不一樣。
佈局
我是這樣設定優先級順序的:動畫
下面將這些約定的可達性用數值來體現以便比較,設這個值爲accessibility,值越大優先級越高。
一路通行的方向
accessibility = 1/stepToEdge; //stepToEdge表示離邊緣還有幾步
會出現路障的方向
accessibility = (-1)/stepToBlock;//stepToBlock表示離路障的距離
接下來考慮分母若是爲0怎麼辦,在第一種狀況中,分母爲0,表示貓當前已經在邊緣了,那麼也不用判斷優先級了,遊戲已經失敗了。第二種狀況中,分母爲0表示出門即遇路障,這個方向不用考慮了是絕對走不通的,那麼它的優先級就定爲-1。
這樣一輪算下來,六個方向上的accessibility值分別爲:
這樣比較下來優先級應該是左>右上>右下>左下>左上>右。
爲何左上與右,右上與右下,這兩組內部的值明明同樣,咱們依然是排出了順序呢?只是由於咱們計算是從左方向開始順時針旋轉的。若是值同樣,那就看出現的順序了。
因此在上圖中這種狀況下,貓會向左走一步。
在網上玩這個遊戲的時候,我發現當貓被圍住的時候會換成一種「被圍住」的動做,那麼該如何判斷貓被圍住了,而後改變它的動做動畫?
「被圍住」與「被抓住」不同,它早於「被抓住」的狀態。當貓無路可走的時候,它就「被抓住」了,遊戲獲勝。而「被圍住」指的是貓暫時還有路可走,可是已經被包圍住了,垂死掙扎而已,以下圖。
個人思路是這樣的:
從貓當前的位置找六個方向中可通行的鄰居,而後從這些鄰居出發,再找它們各自的可通行鄰居,一直這樣找下去,一邊找的過程當中,一邊判斷當前已經找到的鄰居中有沒有處在遊戲區邊緣的,若是有,那麼尋找過程提早結束,判斷結果是:貓沒有被圍住。若是直到全部的可通行鄰居都找到了,裏面都沒有處在遊戲區邊緣的,那麼判斷結果是:貓被圍住了。
接下來用代碼實現這個判斷過程。
首先,須要準備一個方法,判斷圓圈是否已經處在圓圈邊緣了,假設這個方法名及參數以下,內部實現比較簡單這裏就不貼了。
/* 判斷傳入的circle是否在邊界上 */ private isCircleAtEdge(circle:Circle):boolean { ... }
再準備一個方法,獲取某圓圈周圍某方向的鄰居。
private getCircleNeighbor(circle:Circle,direction:Direction):Circle{ ... }
最後,是判斷的核心方法。
/* 可否在circle位置出發找到路線到達邊緣 */ private canExitAt(circle:Circle):boolean{ var ignoreArr=[];//不用再處理的circle集合 var toDealWithArr=[circle];//還需進行判斷的circle集合 while(true){ if(toDealWithArr.length<1){ return false; }else{ var _first=toDealWithArr.shift(); ignoreArr.push(_first); if(_first.getStatus()!==CircleStatus.Blocked&&this.isCircleAtEdge(_first)){ return true; }else{ for(var i=Direction.LEFT;i<=Direction.BOTTOM_LEFT;i++){ var nbr=this.getCircleNeighbor(_first,i); if(!(ignoreArr.indexOf(nbr)>-1||toDealWithArr.indexOf(nbr)>-1)) if(nbr.getStatus()!==CircleStatus.Available){ ignoreArr.push(nbr); }else{ toDealWithArr.push(nbr); } } } } } }
在方法體的最開始,準備好兩個數組,一個用來存儲不用再處理的圓圈集合ignoreArr,另外一個用來存儲還須要進行判斷的圓圈集合toDealWithArr。每找到一個可通行的鄰居,首先要判斷它是否是第一次出現(由於幾個圓圈可能會有共同的鄰居,因此一個圓圈可能由於它是多個圓圈的鄰居而被找到屢次),判斷的標準就是它有沒有出如今ignoreArr或toDealWithArr裏,若是沒有那麼就是第一次出現,若是它是路障,那麼塞到ignoreArr,若是不是路障,那麼推入toDealWithArr尾部等待判斷。
每次循環開始時,咱們會從toDealWithArr頭部彈出一個圓圈對象,對它是否在邊緣作判斷,若是是,那麼返回true跳出循環,貓沒有被圍住,它能夠經過某條路線到達邊緣。若是toDealWithArr所有判斷完了都不在邊緣,那麼返回false,貓被圍住了,它的直接鄰居及衆多間接鄰居中沒有一個是在邊緣的。
完整的代碼能夠戳個人Github→sheila1227/HTML5-GAME-shenjingcat
在線試玩能夠戳→圍住神經貓
有任何不妥之處或錯誤歡迎各位指出,不勝感激~