1月份的時候微信更新了小遊戲的功能,微信公衆平台也放出了小遊戲的開發文檔,這裡總結一下最近對小遊戲的學習。
登入微信公衆平台,能發現小程式的開發文檔下多了一個小遊戲類别。按照文檔的指引,在開發工具中建立項目時勾選“建立遊戲快速啟動模闆”就可以得到一個可以運作的小遊戲了。

上圖可以看到一個飛機的遊戲,在開發工具中預覽遊戲,可以進行試玩。接下來就學習一下這個飛機遊戲的代碼。
項目的完整目錄結構
|
|---audio
| |... // 音頻檔案
|---images
| |... // 圖檔/動畫資源
|---js
| |---base
| | |---animation.js // Sprite的子類,實作了動畫相關的功能
| | |---pool.js // 一個簡單的對象池實作,減少對象建立開銷和頻繁的垃圾回收
| | |---sprite.js // 遊戲基礎的精靈類
| |---libs
| | |---symbol.js // 對于ES6中Symbol的極簡相容,友善模拟私有變量
| | |---weapp-adapter.js // 模拟BOM和DOM的代碼庫,使遊戲引擎在調用DOM API和通路DOM屬性時不産生錯誤
| |---npc
| | |---enemy.js
| |---player
| | |---bullet.js
| | |---index.js
| |---runtime
| | |---background.js
| | |---gameinfo.js
| | |--music.js
| |---databus.js // 全局狀态管理器
| |---main.js // 遊戲主函數
|---README.md
|---game.js // [必要]小遊戲的入口檔案
|---game.json // [必要]配置檔案
|---project.config.json // 項目相關的配置檔案
可以看到雖然隻是一個模闆,但包含的檔案很多。不過檔案雖多,結構還是很清晰的。首先從入口檔案game.js開始。
game.js
import './js/libs/weapp-adapter'
import './js/libs/symbol'
import Main from './js/main'
new Main()
執行的代碼隻有一行:new Main()。接着來到main.js。順着Main類中的constructor,來到restart()中:
restart() {
databus.reset()
canvas.removeEventListener(
'touchstart',
this.touchHandler
)
this.bg = new BackGround(ctx)
this.player = new Player(ctx)
this.gameinfo = new GameInfo()
this.music = new Music()
this.bindLoop = this.loop.bind(this)
this.hasEventBind = false
// 清除上一局的動畫
window.cancelAnimationFrame(this.aniId);
this.aniId = window.requestAnimationFrame(
this.bindLoop,
canvas
)
}
這個函數中做了一些初始化工作,移除了重開遊戲對話框的Listener,然後是最重要的一步:
this.aniId = window.requestAnimationFrame(
this.bindLoop,
canvas
)
window.requestAnimationFrame是adapter封裝的接口,内部是微信提供的接口[requestAnimationFrame()](“https://mp.weixin.qq.com/debug/wxagame/dev/document/render/frame/requestAnimationFrame.html“)。參數中的bindLoop就是main中的loop函數,在loop中同樣調用了window.requestAnimationFrame,進而使得每一幀都會調用一次loop(),進而實作了遊戲的幀循環。
接下來就到了loop()中了。
loop() {
databus.frame++
this.update()
this.render()
this.aniId = window.requestAnimationFrame(
this.bindLoop,
canvas
)
}
databus.frame記錄了遊戲開始到現在的幀數,在生成敵人和計算開炮時機的時候會用到。update中計算玩家和敵人的移動、碰撞等,render負責在畫布上繪制需要展示的元素。這些都和主流的遊戲結構類似。
最後來看看Sprite和Animation兩個類。
Sprite類比較簡單,其中儲存了圖檔路徑、大小、位置以及是否可見等資訊,并實作了繪制到畫布(drawToCanvas)的方法和一個簡單的碰撞檢測(isCollideWith)。碰撞檢測檢查的是一個精靈的中心點是否位于本精靈的矩形内。
Animation要稍微複雜一點,它繼承了Sprite類,實作了播放幀動畫的功能。由于隻是個簡單的實作,是以隻支援了一個幀動畫,當然簡單修改之後就可以支援多個幀動畫,更能滿足實際應用的需求。從代碼中可以看出幀動畫是通過将精靈本體設定為不可見,再通過一個定時器(setInterval)按照一個固定的速率(this.interval)依次切換幀動畫序列中的幀圖檔,主循環進行渲染時會把該圖檔顯示到畫布,達到動畫的效果。這裡比較重要的是setInterval方法,它是微信提供的一個定時器api,作用是設定一個定時器,按照指定的周期來執行注冊的回調函數。這裡的回調函數的工作就是切換幀圖檔的index。當動畫播放結束時,要結束這個定時器,這時就需要使用微信提供的clearInterval接口了。
這裡簡單總結了一下微信開發者工具中提供的小遊戲模闆,可以看到整個遊戲的生命周期都是由自己編寫代碼實作的,不像在一些引擎中隻用“填空”即可。有點奇怪的是動畫類是自己實作的,實際在寫代碼時,會發現提示中是有wx.createAnimation接口的,但文檔中并沒有給出來,可能以後會開放吧。
期待微信開發工具更新更多功能,并早日開放個人開發者釋出微信小遊戲的權限。