1.初識
微信小游戲目前的主要入口有下面幾個(gè):
群或好友分享
識別小游戲二維碼
微信聊天列表頁面下拉后出現(xiàn)最近玩過的小游戲
發(fā)現(xiàn) - 小程序
發(fā)現(xiàn) - 游戲 - 我的小游戲小游戲的運(yùn)行環(huán)境其實(shí)是微信的原生環(huán)境磕瓷,游戲的 JavaScript 代碼并不是通過瀏覽器來執(zhí)行的筋栋,而是通過圖中 JS VM 層獨(dú)立的 JavaScript 引擎來執(zhí)行的俭识。 在 Android 平臺使用 Google 的 v8 引擎瞻离,而在 iOS 上則使用蘋果的 JavaScript Core 引擎囊卜。
當(dāng)然 JS 引擎只負(fù)責(zé)解釋執(zhí)行 JS 邏輯,并沒有支持渲染接口橡伞,那么渲染接口和諸多的微信功能接口又是怎么實(shí)現(xiàn)的呢批钠?這就不得不提到腳本綁定技術(shù),這種技術(shù)可以將某種原生語言的接口橋接到腳本接口上怠苔,當(dāng)在腳本層調(diào)用接口時(shí)同廉,會自動轉(zhuǎn)發(fā)到原生層,調(diào)用原生接口柑司。微信小游戲環(huán)境用的就是這樣的技術(shù)迫肖,將 iOS / Android 原生平臺實(shí)現(xiàn)的渲染、用戶攒驰、網(wǎng)絡(luò)咒程、音視頻等接口綁定為 JavaScript 接口。這也就是圖中的微信原生層模塊到小游戲?qū)幽K的原理讼育。
不過除了這些常規(guī)玩法以外帐姻,最讓人欣喜的是通過轉(zhuǎn)發(fā)小游戲稠集,可以完成玩家在游戲中的組隊(duì)或?qū)?zhàn),加上小游戲即點(diǎn)即玩的特點(diǎn)饥瓷,這種邀戰(zhàn)的游戲體驗(yàn)可以說是天衣無縫剥纷。
游戲資質(zhì)提交及類目確認(rèn)
確認(rèn)游戲類目,并且提交資質(zhì)文檔呢铆。
- 非個(gè)人主體需提交:《廣電總局版號批文》 晦鞋、《文化部備案信息》、《計(jì)算機(jī)軟件著作權(quán)登記證書》棺克、《游戲自審自查報(bào)告》
- 個(gè)人主體需提交:《計(jì)算機(jī)軟件著作權(quán)登記證書》悠垛、《游戲自審自查報(bào)告》
組成
1.底層技術(shù)
首先是開發(fā)語言,微信小游戲只支持 JavaScript娜谊,當(dāng)然可以編譯為 JS 的 TypeScript 以及 CoffeeScript 都可以作為開發(fā)語言使用确买。
其次是小游戲所支持的游戲庫 API,主要包含 HTML5 的 Canvas 2D API 和 WebGL 1.0 API纱皆,使用任何一種 API 都可以完成游戲最重要的渲染功能湾趾,不過不能夠混用,除此之外派草,只有 WebGL 渲染模式可以支持 3D 渲染搀缠。
2.中間件:游戲引擎
當(dāng)然,直接使用 Canvas 2D 或 WebGL 來制作游戲是門檻很高近迁,也非常費(fèi)時(shí)費(fèi)力的一件事艺普,你肯定不希望一個(gè)小游戲項(xiàng)目拖上一年半載吧?所以使用 HTML5 游戲引擎其實(shí)是非常明智的選擇鉴竭,引擎封裝出的高層接口可以大大降低開發(fā)者的開發(fā)門檻歧譬,縮短項(xiàng)目周期。目前國內(nèi)的三家主流引擎 Cocos Creator拓瞪、Egret缴罗、Laya 均已支持小游戲發(fā)布助琐,Phaser.js祭埂、Three.js 等國外 HTML5 引擎雖然并沒有支持直接發(fā)布,經(jīng)過一些定制也是可以成功運(yùn)行在小游戲環(huán)境中兵钮。
3.微信 SDK
除此之外蛆橡,微信小游戲還提供了豐富的微信內(nèi)部 SDK 供開發(fā)者調(diào)用,使用這些接口可以完成用戶登陸掘譬、轉(zhuǎn)發(fā)泰演、排行榜等常規(guī)的社交功能。
文件結(jié)構(gòu)
- game.js 小游戲入口文件
- game.json 配置文件
小游戲開發(fā)者通過在根目錄編寫一個(gè) game.json
文件進(jìn)行配置葱轩,開發(fā)者工具和客戶端需要讀取這個(gè)配置睦焕,完成相關(guān)界面渲染和屬性設(shè)置藐握。
key | 數(shù)據(jù)類型 | 說明 | 默認(rèn)值 |
---|---|---|---|
deviceOrientation | String | 支持的屏幕方向 | portrait |
showStatusBar | Boolean | 是否顯示狀態(tài)欄 | false |
networkTimeout | Number | 網(wǎng)絡(luò)請求的超時(shí)時(shí)間,單位:毫秒 | 60000 |
networkTimeout.request | Number | wx.request 的超時(shí)時(shí)間垃喊,單位:毫秒 | 60000 |
networkTimeout.connectSocket | Number | wx.connectSocket 的超時(shí)時(shí)間猾普,單位:毫秒 | 60000 |
networkTimeout.uploadFile | Number | wx.uploadFile 的超時(shí)時(shí)間,單位:毫秒 | 60000 |
networkTimeout.downloadFile | Number | wx.downloadFile 的超時(shí)時(shí)間本谜,單位:毫秒 | 60000 |
workers | String | 多線程 Worker 配置項(xiàng)初家,詳細(xì)請參考 Worker文檔 | 無 |
生命周期
1.wx.exitMiniProgram(Object object)
退出當(dāng)前小游戲
2.LaunchOption wx.getLaunchOptionsSync()
返回小程序啟動參數(shù)
3.wx.onHide(function callback)
監(jiān)聽小游戲隱藏到后臺事件。鎖屏乌助、按 HOME 鍵退到桌面溜在、顯示在聊天頂部等操作會觸發(fā)此事件。
4.wx.offHide(function callback)
取消監(jiān)聽小游戲隱藏到后臺事件他托。鎖屏掖肋、按 HOME 鍵退到桌面、顯示在聊天頂部等操作會觸發(fā)此事件上祈。
5.wx.onShow(function callback)
監(jiān)聽小游戲回到前臺的事件
6.wx.offShow(function callback)
取消監(jiān)聽小游戲回到前臺的事件
2.wx API
你只能使用 JavaScript 來編寫小游戲培遵。小游戲的運(yùn)行環(huán)境是一個(gè) 綁定了一些方法的 JavaScript VM。不同于瀏覽器登刺,這個(gè)運(yùn)行環(huán)境沒有 BOM 和 DOM API籽腕,只有 wx API。接下來我們將介紹如何用 wx API 來完成創(chuàng)建畫布纸俭、繪制圖形皇耗、顯示圖片以及響應(yīng)用戶交互等基礎(chǔ)功能。
創(chuàng)建 Canvas
調(diào)用 [wx.createCanvas()] 接口揍很,可以創(chuàng)建一個(gè) [Canvas]對象郎楼。
var canvas = wx.createCanvas()
此時(shí)創(chuàng)建的 canvas 是一個(gè)上屏 Canvas,已經(jīng)顯示在了屏幕上窒悔,且與屏幕等寬等高呜袁。
console.log(canvas.width, canvas.height)
在整個(gè)小游戲代碼中首次調(diào)用 wx.createCanvas() 創(chuàng)建的是上屏 Canvas,之后調(diào)用則創(chuàng)建的是離屏 Canvas简珠。如果你的項(xiàng)目中使用了官方提供的 [Adapter] 即 weapp-adapter.js(關(guān)于什么是 Adpater 請參考官方教程 [Adapter]阶界,那么你此時(shí)創(chuàng)建的會是一個(gè)離屏 Canvas。因?yàn)樵?weapp-adapter.js 已經(jīng)調(diào)用了一次 wx.createCanvas()聋庵,并把返回的 canvas 作為全局變量暴露出來
在 Canvas 上進(jìn)行繪制
但是由于沒有在 canvas 上進(jìn)行繪制膘融,所以 canvas 是透明的。使用 2d 渲染上下文的進(jìn)行簡單的繪制祭玉,可以在屏幕左上角看到一個(gè) 100x100 的紅色矩形氧映。
var context = canvas.getContext('2d')
context.fillStyle = 'red'
context.fillRect(0, 0, 100, 100)
顯示圖片
通過 [wx.createImage()]接口,可以創(chuàng)建一個(gè) [Image] 對象脱货。Image 對象可以加載圖片岛都。當(dāng) Image 對象被繪制到 Canvas 上時(shí)律姨,圖片才會顯示在屏幕上。
var image = wx.createImage()
設(shè)置 Image 對象的 src 屬性可以加載一張本地圖片或網(wǎng)絡(luò)圖片臼疫,當(dāng)圖片加載完畢時(shí)會執(zhí)行注冊的 onload 回調(diào)函數(shù)线召,此時(shí)可以將 Image 對象繪制到 Canvas 上。
image.onload = function () {
console.log(image.width, image.height)
context.drawImage(image, 0, 0)
}
image.src = 'logo.png'
動畫
在 JavaScript 中多矮,一般通過 setInterval/setTimeout/requestAnimationFrame 來實(shí)現(xiàn)動畫效果缓淹。小游戲?qū)@些 API 提供了支持:
- [setInterval()]
- [setTimeout()]
- [requestAnimationFrame()]
- [clearInterval()]
- [clearTimeout()]
- [cancelAnimationFrame()]
另外,還可以通過 [wx.setPreferredFramesPerSecond()]修改執(zhí)行 requestAnimationFrame 回調(diào)函數(shù)的頻率塔逃,以降低性能消耗讯壶。
觸摸事件
響應(yīng)用戶與屏幕的交互是游戲中必不可少的部分,小游戲參照 DOM 中的 TouchEvent 提供了以下監(jiān)聽觸摸事件的 API:
- wx.onTouchStart()
- wx.onTouchMove()
- wx.onTouchEnd()
- wx.onTouchCancel()
全局對象
window 對象是瀏覽器環(huán)境下的全局對象湾盗。小游戲的運(yùn)行環(huán)境中沒有 BOM API伏蚊,因此沒有 window 對象。但是提供了全局對象 GameGlobal格粪,所有全局定義的變量都是 GameGlobal 的屬性躏吊。
console.log(GameGlobal.setTimeout === setTimeout)
console.log(GameGlobal.requestAnimationFrame === requestAnimationFrame)
// true
開發(fā)者可以根據(jù)需要把自己封裝的類和函數(shù)掛載到 GameGlobal 上。
GameGlobal.render = function () {
//省略方法的具體實(shí)現(xiàn)...
}
render()
GameGlobal 是一個(gè)全局對象帐萎,本身也是一個(gè)存在循環(huán)引用的對象比伏。
console.log(GameGlobal === GameGlobal.GameGlobal)
console.log 無法在真機(jī)上將存在循環(huán)引用的對象輸出到 vConsole 中。因此真機(jī)調(diào)試時(shí)請注釋 console.log(GameGlobal) 這樣的代碼疆导,否則將會產(chǎn)生這樣的錯(cuò)誤
An object width circular reference can't be logged
3.Adapter
小游戲的運(yùn)行環(huán)境在 iOS 上是 [JavaScriptCore]赁项,在 Android 上是 [V8],都是沒有 BOM 和 DOM 的運(yùn)行環(huán)境澈段,沒有全局的 document 和 window 對象悠菜。因此當(dāng)你希望使用 DOM API 來創(chuàng)建 Canvas 和 Image 等元素的時(shí)候,會引發(fā)錯(cuò)誤败富。
var canvas = document.createElement('canvas')
但是我們可以使用 wx.createCanvas 和 wx.createImage 來封裝一個(gè) document悔醋。
var document = {
createElement: function (tagName) {
tagName = tagName.toLowerCase()
if (tagName === 'canvas') {
return wx.createCanvas()
}
else if (tagName === 'image') {
return wx.createImage()
}
}
}
這時(shí)代碼就可以像在瀏覽器中創(chuàng)建元素一樣創(chuàng)建 Canvas 和 Image 了。
var canvas = document.createElement('canvas')
var image = document.createImage('image')
同樣兽叮,如果想實(shí)現(xiàn) new Image() 的方式創(chuàng)建 Image 對象芬骄,只須添加如下代碼。
function Image () {
return wx.createImage()
}
weapp-adapter 對瀏覽器環(huán)境的模擬遠(yuǎn)不完整的充择,僅僅只針對游戲引擎可能訪問的屬性和調(diào)用的方法進(jìn)行了模擬德玫,也不保證所有游戲引擎都能通過 weapp-adapter 順利無縫接入小游戲匪蟀。直接將 weapp-adapter 提供給開發(fā)者椎麦,更多地是作為參考,開發(fā)者可以根據(jù)需要在 weapp-adapter 的基礎(chǔ)上進(jìn)行擴(kuò)展材彪,以適配自己項(xiàng)目使用的游戲引擎观挎。
4.對引擎的支持
隨著用戶的交互更新畫面和播放聲音琴儿。小游戲的開發(fā)語言是 JavaScript,那么在引擎的底層就需要通過 JavaScript 調(diào)用繪制 API 和音頻 API嘁捷。
小游戲的運(yùn)行環(huán)境是一個(gè)不同于瀏覽器的宿主環(huán)境造成,沒有提供 BOM 和 DOM API,提供的是 wx API雄嚣。通過 wx API晒屎,開發(fā)者可以調(diào)用 Native 提供的繪制、音視頻缓升、網(wǎng)絡(luò)鼓鲁、文件等能力。
創(chuàng)建畫布港谊,你需要調(diào)用 wx.createCanvas()
let canvas = wx.createCanvas()
let context = canvas.getContext('2d')
創(chuàng)建一個(gè)音頻對象骇吭,你需要調(diào)用 wx.createInnerAudioContext()
let audio = wx.createInnerAudioContext()
// src 地址僅作演示,并不真實(shí)存在
audio.src = 'bgm.mp3'
audio.play()
獲取屏幕的寬高歧寺,你需要調(diào)用 [wx.getSystemInfoSync()]
let { screenWidth, screenHeight } = wx.getSystemInfoSync()
5.模塊化
小游戲提供了 CommonJS 風(fēng)格的模塊 API燥狰,可以通過 module.exports 和 exports 導(dǎo)出模塊,通過 require 引入模塊斜筐。
drawLogo.js 模塊封裝的是一個(gè)用來把 logo 畫到指定位置的方法龙致。
module.exports = function (canvas, x, y) {
var image = new Image()
image.onload = function () {
var context = canvas.getContext('2d')
context.drawImage(image, x, y)
}
image.src = 'res/image/logo.png'
}
注意,當(dāng)用加載本地的圖片顷链、音頻净当、視頻資源時(shí),必須寫從代碼包根目錄開始的絕對路徑蕴潦。如果寫以 drawLogo.js 所在目錄的相對路徑像啼,則會導(dǎo)致系統(tǒng)找不到資源文件,加載失敗潭苞。
image.src = '../../res/image/logo.png'
在 game.js 中 require drawLogo忽冻,就可以調(diào)用 drawLogo 模塊導(dǎo)出的方法。
var drawLogo = require('./src/util/drawLogo')
var canvas = wx.createCanvas()
drawLogo(canvas, 40, 40)
6.音頻播放
小游戲內(nèi)只有一種音頻播放的方式此疹,即使用 InnerAudioContext 來播放僧诚。
使用 InnerAudioContext 播放
通過 [wx.createInnerAudioContext()]接口可以創(chuàng)建一個(gè)音頻實(shí)例 [innerAudioContext],通過這個(gè)實(shí)例可以播放音頻蝗碎。
var audio = wx.createInnerAudioContext()
audio.src = url // src 可以設(shè)置 http(s) 的路徑湖笨,本地文件路徑或者代碼包文件路徑
audio.play()
在 iOS 系統(tǒng)上,默認(rèn)遵循靜音鍵設(shè)置蹦骑。如果希望在靜音時(shí)也能播放聲音慈省,可以設(shè)置 obeyMuteSwitch
為 false
。
audio.obeyMuteSwitch = false
自動播放和循環(huán)播放
設(shè)置 autoplay 和 loop 屬性可以自動播放和循環(huán)播放音頻眠菇,一般適用于背景音樂边败。
var bgm = wx.createInnerAudioContext()
bgm.autoplay = true
bgm.loop = true
bgm.src = url
回到前臺時(shí)恢復(fù)背景音樂
當(dāng)小游戲被隱藏到后臺時(shí)袱衷,所有音頻會被暫停,并在回到前臺之前都不能再播放成功笑窜。
回到前臺之后致燥,被暫停的音頻不會自動繼續(xù)播放,如果小游戲有背景音樂的話排截,需要監(jiān)聽回到前臺事件嫌蚤,并在收到回到前臺事件之后調(diào)用背景音樂繼續(xù)播放。
wx.onShow(function () {
bgm.play()
})
處理音頻中斷事件
音頻中斷事件指的是在游戲期間断傲,音頻被系統(tǒng)打斷時(shí)觸發(fā)的事件搬葬。音頻中斷事件分為中斷開始和中斷結(jié)束事件,分別使用 wx.onAudioInterruptionBegin()和 wx.onAudioInterruptionEnd()來監(jiān)聽艳悔。
以下事件會觸發(fā)音頻中斷開始事件:接到電話急凰、鬧鐘響起、系統(tǒng)提醒猜年、收到微信好友的語音/視頻通話請求抡锈。被中斷之后,小游戲內(nèi)所有音頻會被暫停乔外,并在中斷結(jié)束之前都不能再播放成功床三。
中斷結(jié)束之后,被暫停的音頻不會自動繼續(xù)播放杨幼,如果小游戲有背景音樂的話撇簿,需要監(jiān)聽音頻中斷結(jié)束事件,并在收到中斷結(jié)束事件之后調(diào)用背景音樂繼續(xù)播放差购。
wx.onAudioInterruptionEnd(function () {
bgm.play()
})
如果小游戲的邏輯強(qiáng)依賴音樂的播放四瘫,則需要在音頻開始中斷的時(shí)候暫停游戲
wx.onAudioInterruptionBegin(function () {
// 暫停游戲
})
及時(shí)銷毀不需要的音頻實(shí)例
如果一個(gè)音頻不再需要使用了,可以調(diào)用 InnerAudioContext.destroy() 接口提前銷毀這個(gè)實(shí)例欲逃。
Android 同時(shí)播放的音頻數(shù)量限制
由于系統(tǒng)限制找蜜,在 Android 上最多同時(shí)播放 10 個(gè)音頻,超過的部分會做有損處理稳析,對開發(fā)者來說不感知洗做,但開發(fā)者應(yīng)盡量避免同時(shí)播放過多音頻。
7.文件系統(tǒng)
文件系統(tǒng)有兩類文件:代碼包文件和本地文件彰居。
文件系統(tǒng)管理接口
通過 [wx.getFileSystemManager()]可以獲取到全局唯一的文件系統(tǒng)管理器诚纸,所有文件系統(tǒng)的管理操作通過 [FileSystemManager]來調(diào)用。
var fs = wx.getFileSystemManager()
代碼包文件
代碼包文件指的是在項(xiàng)目目錄中添加的文件陈惰。由于代碼包文件大小限制畦徘,代碼包文件適用于放置首次加載時(shí)需要的文件,對于內(nèi)容較大或需要動態(tài)替換的文件,不推薦用添加到代碼包中旧烧,推薦在小游戲啟動之后再用下載接口下載到本地。
修改代碼包文件
代碼包內(nèi)的文件無法在運(yùn)行后動態(tài)修改或刪除画髓,修改代碼包文件需要重新發(fā)布版本掘剪。
本地文件
本地文件指的是小程序被用戶添加到手機(jī)后,會有一塊獨(dú)立的文件存儲區(qū)域奈虾,以用戶維度隔離夺谁。即同一臺手機(jī),每個(gè)微信用戶不能訪問到其他登錄用戶的文件肉微,同一個(gè)用戶不同 appId 之間的文件也不能互相訪問匾鸥。
本地文件的文件路徑均為以下格式:
{{協(xié)議名}}://文件路徑
其中,協(xié)議名在 iOS/Android 客戶端為
"wxfile"
碉纳,在開發(fā)者工具上為"http"
勿负,開發(fā)者無需關(guān)注這個(gè)差異,也不應(yīng)在代碼中去硬編碼完整文件路徑劳曹。
本地臨時(shí)文件
本地臨時(shí)文件只能通過調(diào)用特定接口產(chǎn)生奴愉,不能直接寫入內(nèi)容。本地臨時(shí)文件產(chǎn)生后铁孵,僅在當(dāng)前生命周期內(nèi)有效锭硼,重啟之后即不可用。因此蜕劝,不可把本地臨時(shí)文件路徑存儲起來下次使用檀头。如果需要下次在使用,可通過 FileSystemManager.saveFile()或 FileSystemManager.copyFile()接口把本地臨時(shí)文件轉(zhuǎn)換成本地存儲文件或本地用戶文件岖沛。
示例
wx.chooseImage({
success: function (res) {
var tempFilePaths = res.tempFilePaths // tempFilePaths 的每一項(xiàng)是一個(gè)本地臨時(shí)文件路徑
}
})
本地緩存文件
本地存儲文件只能通過調(diào)用特定接口產(chǎn)生暑始,不能直接寫入內(nèi)容。本地緩存文件產(chǎn)生后婴削,重啟之后仍可用蒋荚。本地緩存文件只能通過 FileSystemManager.saveFile()接口將本地臨時(shí)文件保存獲得。
示例
fs.saveFile({
tempFilePath: '', // 傳入一個(gè)本地臨時(shí)文件路徑
success(res) {
console.log(res.savedFilePath) // res.savedFilePath 為一個(gè)本地緩存文件路徑
}
})
本地用戶文件
本地用戶文件是從 1.7.0 版本開始新增的概念馆蠕。我們提供了一個(gè)用戶文件目錄給開發(fā)者期升,開發(fā)者對這個(gè)目錄有完全自由的讀寫權(quán)限。通過 wx.env.USER_DATA_PATH 可以獲取到這個(gè)目錄的路徑互躬。
示例
// 在本地用戶文件目錄下創(chuàng)建一個(gè)文件 a.txt播赁,寫入內(nèi)容 "hello,world"
const fs = wx.getFileSystemManager()
fs.writeFileSync(`${wx.env.USER_DATA_PATH}/hello.txt`, 'hello, world', 'utf8')
讀寫權(quán)限:
接口、組件 | 讀 | 寫 |
---|---|---|
代碼包文件 | 有 | 無 |
本地臨時(shí)文件 | 有 | 無 |
本地緩存文件 | 有 | 無 |
本地用戶文件 | 有 | 有 |
8. 垃圾回收
小游戲中吼渡,JavaScript 中的每一個(gè) Canvas 或 Image 對象都會有一個(gè)客戶端層的實(shí)際紋理儲存容为,實(shí)際紋理儲存中存放著 Canvas、Image 的真實(shí)紋理,通常會占用相當(dāng)一部分內(nèi)存坎背。 每個(gè)客戶端實(shí)際紋理儲存的回收時(shí)機(jī)依賴于 JavaScript 中的 Canvas替劈、Image 對象回收。在 JavaScript 的 Canvas得滤、Image 對象被回收之前陨献,客戶端對應(yīng)的實(shí)際紋理儲存不會被回收。通過調(diào)用 [wx.triggerGC()]方法懂更,可以加快觸發(fā) JavaScriptCore Garbage Collection(垃圾回收)眨业,從而觸發(fā) JavaScript 中沒有引用的 Canvas、Image 回收沮协,釋放對應(yīng)的實(shí)際紋理儲存龄捡。 但 GC 具體觸發(fā)時(shí)機(jī)還要取決于 JavaScriptCore 自身機(jī)制,并不能保證調(diào)用 [wx.triggerGC()]能馬上觸發(fā)回收慷暂,建議在每局游戲開始或結(jié)束觸發(fā)一下聘殖。
9.更新
小游戲更新
小游戲啟動會有兩種情況,一種是「冷啟動」行瑞,一種是「熱啟動」就斤。 假如用戶已經(jīng)打開過某小游戲,然后在一定時(shí)間內(nèi)再次打開該小游戲蘑辑,此時(shí)無需重新啟動洋机,只需將后臺態(tài)的小游戲切換到前臺,這個(gè)過程就是熱啟動洋魂;冷啟動指的是用戶首次打開或小游戲被微信主動銷毀后再次打開的情況绷旗,此時(shí)小游戲需要重新加載啟動。
更新機(jī)制
小游戲冷啟動時(shí)如果發(fā)現(xiàn)有新版本副砍,將會異步下載新版本的代碼包衔肢,并同時(shí)用客戶端本地已有的包進(jìn)行啟動,即新版本的小游戲需要等下一次冷啟動才會應(yīng)用上豁翎。 如果需要馬上應(yīng)用最新版本角骤,可以使用 wx.getUpdateManager() API 進(jìn)行處理。
getUpdateManager 的使用示例
v1.9.90 基礎(chǔ)庫以后心剥,可以通過 [wx.getUpdateManager()]獲取全局唯一的版本更新管理器邦尊,用于管理小游戲更新;另外請下載最新版本的開發(fā)者工具(1.02.1803130 以上)才支持在開發(fā)者工具上調(diào)試优烧。
由于是新版本才支持的 API蝉揍,請?jiān)谑褂们跋扰袛嗍欠裰С郑纾?/p>
if (wx.getUpdateManager) {
console.log('支持 wx.getUpdateManager')
}
獲取到 updateManager 實(shí)例后畦娄,updateManager 包含以下方法:
方法 | 參數(shù) | 說明 |
---|---|---|
onCheckForUpdate | callback | 當(dāng)向微信后臺請求完新版本信息又沾,會進(jìn)行回調(diào) |
onUpdateReady | callback | 當(dāng)新版本下載完成弊仪,會進(jìn)行回調(diào) |
onUpdateFailed | callback | 當(dāng)新版本下載失敗,會進(jìn)行回調(diào) |
applyUpdate | 當(dāng)新版本下載完成杖刷,調(diào)用該方法會強(qiáng)制當(dāng)前小游戲應(yīng)用上新版本并重啟 |
onCheckForUpdate(callback) 回調(diào)結(jié)果說明:
屬性 | 類型 | 說明 |
---|---|---|
hasUpdate | Boolean | 是否有新的版本 |
注: 檢查更新操作由微信在小游戲冷啟動時(shí)自動觸發(fā)励饵,不需由開發(fā)者主動觸發(fā),開發(fā)者只需監(jiān)聽檢查結(jié)果即可滑燃。
onUpdateReady(callback) 回調(diào)結(jié)果說明:
當(dāng)微信檢查到小游戲有新版本役听,會主動觸發(fā)下載操作(無需開發(fā)者觸發(fā)),當(dāng)下載完成后不瓶,會通過 onUpdateReady
告知開發(fā)者禾嫉。
onUpdateFailed(callback) 回調(diào)結(jié)果說明:
當(dāng)微信檢查到小游戲有新版本灾杰,會主動觸發(fā)下載操作(無需開發(fā)者觸發(fā))蚊丐,如果下載失敗(可能是網(wǎng)絡(luò)原因等)艳吠,會通過 onUpdateFailed
告知開發(fā)者麦备。
applyUpdate() 說明:
當(dāng)小游戲新版本已經(jīng)下載時(shí)(即收到 onUpdateReady
回調(diào)),可以通過這個(gè)方法強(qiáng)制重啟小游戲并應(yīng)用上最新版本昭娩。
完整使用示例
if (typeof wx.getUpdateManager === 'function') {
const updateManager = wx.getUpdateManager()
updateManager.onCheckForUpdate(function (res) {
// 請求完新版本信息的回調(diào)
console.log(res.hasUpdate)
})
updateManager.onUpdateReady(function () {
// 新的版本已經(jīng)下載好凛篙,調(diào)用 applyUpdate 應(yīng)用新版本并重啟
updateManager.applyUpdate()
})
updateManager.onUpdateFailed(function () {
// 新的版本下載失敗
})
}
10. 多線程 Worker
對于游戲來說,每幀 16ms 是極其寶貴的栏渺,如果有一些可以異步處理的任務(wù)呛梆,可以放置于 [Worker]中運(yùn)行,待運(yùn)行結(jié)束后磕诊,再把結(jié)果返回到主線程填物。[Worker]運(yùn)行于一個(gè)單獨(dú)的全局上下文與線程中,不能直接調(diào)用主線程的方法霎终,[Worker]也不具備渲染的能力滞磺。[Worker]與主線程之間的數(shù)據(jù)傳輸,雙方使用 Worker.postMessage()來發(fā)送數(shù)據(jù)莱褒,Worker.onMessage()來接收數(shù)據(jù)击困,傳輸?shù)臄?shù)據(jù)并不是直接共享,而是被復(fù)制的广凸。
步驟
- 配置 Worker 信息
在 game.json 中可配置 Worker 代碼放置的目錄阅茶,目錄下的代碼將被打包成一個(gè)文件:
配置示例:
{
"workers": "workers"
}
- 添加 Worker 代碼文件
根據(jù)步驟 1 中的配置,在代碼目錄下新建以下兩個(gè)入口文件:
workers/request/index.js
workers/request/utils.js
workers/response/index.js
- 編寫 Worker 代碼
在 workers/request/index.js 編寫 Worker 響應(yīng)代碼
var utils = require('./utils')
// 在 Worker 線程執(zhí)行上下文會全局暴露一個(gè) `worker` 對象谅海,直接調(diào)用 worker.onMeesage/postMessage 即可
worker.onMessage(function (res) {
console.log(res)
})
- 在主線程中初始化 Worker
在主線程的代碼 game.js 中初始化 Worker
var worker = wx.createWorker('workers/request/index.js') // 文件名指定 worker 的入口文件路徑目派,絕對路徑
- 主線程向 Worker 發(fā)送消息
worker.postMessage({
msg: 'hello worker'
})
Tips
- Worker 最大并發(fā)數(shù)量限制為 1 個(gè),創(chuàng)建下一個(gè)前請用 Worker.terminate() 結(jié)束當(dāng)前 Worker
- Worker 內(nèi)代碼只能 require 指定 Worker 路徑內(nèi)的文件胁赢,無法引用其它路徑
- Worker 的入口文件由 wx.createWorker()時(shí)指定企蹭,開發(fā)者可動態(tài)指定 Worker 入口文件
- Worker 內(nèi)不支持
wx
系列的 API - Workers 之間不支持發(fā)送消息