前言
今年9月份跳槽從Android轉向前端H5網頁和H5小遊戲開發,一開始自己學習用Canvas做了拼圖、貪吃蛇大作戰等小遊戲,在公司邊學習邊用phaser寫了個手勢識別的小遊戲,現在公司想嘗試轉型Egret白鷺引擎來開發H5,碰巧最近有個類似圍住神經貓的H5小遊戲專案,所以我就拿圍住神經貓來學習學習練練手。
其實幾個月前,微信小遊戲出現的時候,我就用自己學過一點點Egret,就照著官方的簡單的demo下了一遍,大概瞭解了下,所以這次開發起來也是挺輕鬆的。
可能是我自己學習能力比較好,所以入門比較快,加上Egret用TypeScript來開發,寫法上有點類似於java和kotlin,而我以前就是做Android開發的,所以相對來說上手很快,學習成本降低了很多。
這個遊戲的開發,前前後後共花了一天多的時間,圖片素材和音訊素材是在網上找的(有幾個按鈕還是我自己用photoshop做的),僅用來學習。上午瞭解下,下午就直接上手開發,遊戲中有什麼寫得不好的,還望大神指點指點~
用Egret白鷺引擎寫的圍住神經貓H5遊戲
demo以及原始碼地址
線上demo
(pc端看的話,開啟開發者模式,切換手機模式) game.codebear.cn/nervecat
原始碼地址
原文連結(我的部落格)
Egret白鷺引擎
官網連結:www.egret.com/ 簡單地說,白鷺引擎就是一套H5遊戲開發解決方案,擁有以下產品,其中最核心的就是Egret Engine,其他的都是一些開發輔助工具。關於這些的介紹,還是直接戳上方官網連結去看看吧。

瞭解下圍住神經貓遊戲
遊戲介面




遊戲gif動圖

遊戲玩法介紹
點選螢幕上的白色格子,將神經貓圍起來,別讓貓跑到上下左右四個邊界上,最後貓無路可走就玩家贏了,如果貓跑到了邊界上,貓就贏了。
新建一個專案
下面是安裝和專案建立步驟,具體可看官網教程 我用的是Mac osx系統,所以下面以mac軟體安裝為例。
安裝引擎庫管理工具(Egret Launcher)
直接下載mac版安裝包安裝,安裝完成後開啟Egret Launcher.app,出現以下介面,可以選擇引擎版本下載,我這裡下載了最新的5.2.11版本。


建立專案
直接在Egret Launcher上面點選專案選項,建立專案


- 專案型別這裡選擇Egret 遊戲專案
- 縮放模式[官方文件] 這裡我選擇fixedWide,舞臺寬高為螢幕寬高,背景圖片需要處理一下,可能四周會被裁剪。
專案結構
上面選項選好填好後,點選建立,然後點選專案這裡,就可以用Egret Wing 3開啟專案


- bin-debug: 專案除錯時,所產生的檔案存放於此目錄。
- libs: 庫檔案,包括 Egret 核心庫和其他擴充套件庫存放於此目錄。
- resource: 專案資原始檔存放於此目錄,比如圖片、音訊等。
- scripts: 專案構建和釋出時需要用到的指令碼檔案存放在此目錄。
- src: 專案程式碼檔案存放於此目錄。
- template: 專案模板檔案存放於此目錄。
- egretProperties.json: 專案的配置檔案。具體的配置說明可以參考:EgretProperties說明
- index.html: 入口檔案。具體的配置說明可以參考:入口檔案說明
- manifest.json: 網頁清單檔案。
- tsconfig.json: typescript 編譯配置檔案。
執行專案
用Egret Wing 3開啟專案開啟專案後,直接點選工具欄中的編譯按鈕:



至此,專案算是 新建完成也跑成功了,接下來就開始實現自己的遊戲。
開發神經貓遊戲
專案架構
我有一個習慣,寫專案總喜歡儘可能地提取共用程式碼封裝起來,所以每次寫新專案都會先想好如何架構。由於第一次自己用白鷺寫一個完整的遊戲專案,場景跳轉等實在不知道如何控制,所以看了一下視訊,覺得挺不錯的,所以我的這個專案也是這樣的架構:
- 遊戲分為開始、遊戲、結束三個場景
- 一個場景控制器類,用於控制顯示哪些場景(全域性可呼叫)
- 一個儲存遊戲資料(全域性可用,方便各個場景直接使用)
- 一個工具類(獲取寬高、圖片等)
- ...
於是專案結構就是這樣:

┗ src
┣ common // 存放一些共用的類
┃ ┗ GameUtil.ts // 遊戲工具類,獲取圖片、舞臺寬高等
┣ game // 遊戲相關
┃ ┣ bean // 一些bean,比如貓類、普通圓點
┃ ┃ ┣ Cat.ts // 貓(有座標,狀態,搜尋路徑方法等)
┃ ┃ ┣ GridNode.ts // 格子節點(x,y,狀態等)
┃ ┃ ┣ Point.ts // 圓點(x,y)
┃ ┣ scene // 遊戲場景
┃ ┃ ┣ BaseScene.ts // base場景,所有場景繼承這個
┃ ┃ ┣ EndScene.ts // 結束場景
┃ ┃ ┣ PlayScene.ts // 遊戲場景
┃ ┃ ┗ StartScene.ts // 開始場景
┃ ┣ GameData.ts // 存放遊戲資料
┃ ┗ SceneControlloer.ts // 場景控制器
┣ LoadingUI.ts // 載入頁
┣ Main.ts // 遊戲主類(入口,所有場景都放在這個上面顯示)
┗ Platform.ts // 可用於定義一些window上的物件,介面(比如微信登入等),暫時用不到
複製程式碼
寫遊戲
建好目錄
先按上面專案結構建好各個目錄檔案(內容暫時為空,完後再寫)
修改Main.ts
刪除Main.ts中createGameScene方法裡面的內容、刪除createBitmapByName方法(待會寫到GameUtil類中)和startAnimation方法(不需要),刪除之後的Main.ts是這樣:

實現工具類
common/GameUtil.ts中寫一個GameUtil類,新增getStageHeight(獲取舞臺高度)、getStageWidth(獲取舞臺寬度)、createBitmapByName(根據傳入的名稱建立Bitmap)、createMovieClipByName(根據傳入的名稱建立MovieClip)方法,實現如下:

修改LoadingUI.ts
修改LoadingUI.ts,讓進度條居中顯示

實現BaseScene類
實現BaseScene類,繼承egret.DisplayObjectContainer類,擁有initView方法,之後的所有場景繼承自該類,只需實現initView方法即可

新增背景圖片
在Main.ts的createGameScene方法中新增背景圖片,後面紅色方框內兩句是用於設定場景,初始化場景,暫時先不用理

實現遊戲控制類SceneController.ts
寫SceneController.ts類(場景控制),這是一個單例,有initGame(初始化遊戲,顯示開始遊戲場景)、showPlayScene(顯示遊戲場景)、showLevelTip(開始遊戲時提示關卡的動畫)、showEndScene(顯示結束場景)
實現開始場景1
首先寫開始場景StartScene.ts,很簡單,就一張圖片和一個按鈕,這裡的GameUtil.bitmapToBtn()方法是給元件新增點選縮放效果(類似按鈕),具體實現如下


實現開始場景2
在場景控制類中的initGame方法裡面顯示開始場景,程式碼和效果如下:


實現遊戲場景
遊戲場景PlayScene.ts,遊戲場景有中間一些格子和一隻貓,格子用二維陣列存放,自己實現GridNode.ts繼承自egret.Sprite表示格子節點並可新增到舞臺上(有節點狀態(可走、不可走、有貓)、在陣列中的下標、在舞臺上的座標、格子的大小、格子的背景圖片、遊戲監聽介面(PlayScene.ts實現這個介面,並在建立格子的時候傳進來,用於通知使用者點選哪個格子、貓走哪個格子、誰贏等等)),再來實現貓精靈Cat.ts繼承egret.Sprite(有狀態(有路可走、被圍住但是還有空格可以走,只是走不出去了)、在陣列中的下標、大小、背景、遊戲監聽介面、坐在的格子節點),同時貓還有尋找路徑等方法(後面再說)。 在遊戲控制類中,控制顯示遊戲場景







實現貓搜尋路徑演算法
到這裡,遊戲場景基本完成,現在就來寫最重要的一點,貓搜尋路徑的演算法,分析一下,貓要跑出去,第一步就是要選擇最短路徑,很簡單,用bfs演算法搜尋(只貼主要程式碼,其他可以到github檢視):


優化演算法 上面的演算法等找出左右最短路徑,但隨機走的話,可能走的還不是最優路徑,因為可能某些路徑只有一條路,這種情況很容易被堵掉,那麼需要再實現一個演算法篩選出有多個終點的路徑,因為上一步存放了所有路徑需要走的第一個格子,那麼演算法可以通過判斷第一步格子相同的路徑的數量來選擇,可能得到的就剩下一條路徑(如果還有多條,那就可以隨機選擇一條路徑了)


這還不是最優演算法!!!這個演算法有一種死路也會被選擇(多個路徑需要再第二步之後才會出現,但是第一步走完可能就會被堵死,這種情況我沒有判斷,有興趣的可以自己去實現),另外,如果有其它更好的演算法,歡迎評論區推薦~
實現結束場景
結束場景EndScene.ts



寫在最後
以上寫了遊戲實現的步驟和部分程式碼,具體程式碼可前往github檢視:github.com/CB-ysx/game… 這是我用egret寫的第一個專案,可能某些地方寫的不夠好,希望大家能指點指點~