本文來自「心譚博客」的《基於實時數據庫:在線對戰五子棋小遊戲》,更多文章放在了Github,歡迎交流和Star前端
若是你想看更全面雲開發的免費教程 / 分享,請關注咱們在掘金的官方帳號:「騰訊云云開發」git
遊戲開發,尤爲是微信小遊戲開發,是最近幾年比較熱門的話題。github
本次「雲開發」公開課,將經過實戰「在線對戰五子棋」,一步步帶領你們,在不借助後端的狀況下,利用「小程序 ✖ 雲開發」,獨立完成一款微信小遊戲的開發與上線。數據庫
根據項目初始框架,閱讀教程的同時,逐步完成棋盤繪製、音樂播放、玩家對戰、輸贏斷定等功能,最終實現一個能夠快樂玩耍的在線對戰五子棋。小程序
在這個過程當中,會了解到 Serverless 的一些概念,而且實際應用它們,好比:雲數據庫、雲存儲、雲函數、增值能力。除了這些基本功能,還準備了更多的硬核概念與落地實踐,好比:實時數據庫、聚合搜索、權限控制。後端
完成開發後,上傳而且設置爲體驗版,歡迎邀請更多人來體驗。api
從 TencentCloudBase/tcb-game-gomoku 中下載代碼到本地:數組
git clone https://github.com/TencentCloudBase/tcb-game-gomoku.git
cd tcb-game-gomoku/
複製代碼
切換課程專用的 minigame-study
分支:promise
git checkout minigame-study
複製代碼
⚠️minigame
分支保存着「小遊戲版」的完整代碼,miniprogram
分支保存着「小程序版」的完整代碼。bash
小遊戲版本的核心放在了實時對戰上,中間穿插應用了雲開發的各個方面。若是想體驗完整的流程與交互,請前往miniprogram
分支。
一、打開微信 IDE,點擊左側的小遊戲,選擇右側的導入項目,導入以前下載的「在線對戰五子棋」的目錄,AppID 修改成你已經註冊好的小遊戲 AppID。
二、進入後,點擊上方的雲開發按鈕。若是以前沒有開經過雲開發,須要開通雲開發,新開通的話須要等待 10 ~ 20 分鐘。
三、進入「雲開發/數據庫」,建立新的集合,新集合的名稱是rooms
。
四、進入「雲開發/存儲」,點擊「上傳文件」。上傳的內容是/static/
下的bgm.mp3
和 fall.mp3
。以後的代碼中會經過雲存儲的接口,請求文件的臨時 url,這樣作的目的是減小用戶首次進入遊戲加載的靜態資源。
建立配置文件:
cp miniprogram/shared/config.example.js miniprogram/shared/config.js
複製代碼
將關鍵字段的信息,換成本身帳號的信息便可:
打開 miniprogram/shared/cloud.js
,在裏面初始化雲開發能力,而且對外暴露雲數據庫以及聚合搜索的 API。
爲了減小用戶首屏加載的靜態資源,音樂資源並無放在miniprogram
目錄下,而是放在了雲存儲中,經過調用雲存儲的 api 接口,來返回靜態資源的臨時連接。
在 miniprogram/modules/music.js
中,會調用資源接口,獲取資源連接:
getTempFileURL
函數屬於雲開發相關,所以放在了 miniprogram/shared/cloud.js
中。這裏只須要臨時連接tempFileURL
屬性,其它返回值直接過濾調便可。
爲了方便外面調用,promise 內部再也不用 reject 拋錯。對於錯誤異常,返回空字符串。這樣,加載失敗的資源不會影響正常資源的加載和 Promise.all 中邏輯進行。
根據前面的流程圖咱們能夠看到,遊戲玩家的身份是分爲 owner 與 player。它們的含義以下:
判斷的依據就是 judgeIdentity
方法中,讀取雲數據庫集合中的 rooms 的記錄。若是存在多個空閒房間,須要選取建立時間最近的一個房間。所以,這裏須要用到「聚合搜索」的邏輯。
聚合搜索的條件,在這裏有 3 個:
在上述的身份判斷函數邏輯中,若是聚合搜索查詢的結果爲空,說明沒有空閒房間,玩家須要做爲 owner 來建立新的房間,等待其它玩家加入。
建立房間的邏輯就是將約定好的字段,放進雲數據庫的記錄中。這些字段有:
String
>: 6 位房間號,惟一"white" | "black"
>: 下一步是白棋/黑棋走String
>: 編碼後的棋盤數據String
>: 記錄建立時間戳,精確到 msNumber
>: 房間人數是的,你可能注意到了,這裏須要保證 roomid 是不重複的。所以本地生成的隨機 roomid,須要先調用雲數據庫的查詢接口,檢測是否存在。若是存在,那麼遞歸調用,從新生成隨機字符串。
對於 owner 身份來講,除了要建立新房間,還須要在建立後監聽 player 身份的玩家進入遊戲。
對於 player 身份的玩家進入遊戲後,會更新記錄中的 people 字段(1 => 2)。這時候就須要利用「實時數據庫」的功能,監聽遠程記錄的 people 字段變化。
代碼實現上,調用watch
方法,而且傳遞onChange
函數參數。一旦有任何風吹草動,均可以在onChange
回調函數中得到。對於傳遞給回調函數的參數,有兩個比較重要:
Array
>: 數組中的每一項對應每條記錄的變化類型,變化類型有 init、update、delete 等。Array
>: 數組中的每一項對應每條記錄的當前數據。對於 player 身份來講,進入房間後,既不須要「建立新房間」,也不須要「監聽玩家進入」。但須要更新記錄的 people 字段。因爲記錄是由 owner 身份的玩家建立的,而云數據庫只有如下 4 種權限:
以上 4 種權限,並無「全部用戶可讀寫」。所以,對於越權讀寫的狀況,須要經過調用雲函數來以「管理員」的權限實現。在 cloudfunction
中建立 updateDoc
雲函數,接收前端傳來的 collection、docid、data 字段。對於 data 字段來講,就是數據記錄的最新更新數據。
在小遊戲中,經過wx.cloud.callFunction
來調用雲函數。傳入的 data 字段指明被調用的雲函數,傳入的 data 字段能夠在雲函數的回調函數的 event 參數中訪問到(如上圖所示)。
不論對於 player 仍是 owner 身份,都須要處理落子的邏輯。落子邏輯中,下面的兩種狀況是屬於無效落子:
對於以上兩種狀況,處理的邏輯分別是:
落子成功後,要在本地判斷是否勝利。若是勝利,須要調用退出的邏輯。但不管是否勝利,都要將本地的最新狀態更新到雲端。
不論對於 player 仍是 owner 身份的玩家,都須要監聽遠程棋盤的更新邏輯。當遠程棋盤字段更新時,本地根據最新的棋盤狀態,重繪整個棋盤。而且進行輸贏斷定,若是能夠斷定輸贏,則退出遊戲;不然,打開本地的鎖,玩家能夠落子。
由於不一樣身份均須要監聽,所以這一塊的監聽邏輯能夠複用。不一樣的是,兩種身份的監聽啓動時間不同。owner 身份須要等待 player 身份玩家進入遊戲後纔開啓棋盤監聽;player 身份是更新了 people 字段後,開啓棋盤監聽。
在監聽邏輯中,須要判斷遠程更新的字段是不是 chessmen,這是經過前面說起的 dataType 來實現的。還徐喲啊判斷記錄中的 nextcolor 字段是否和本地的 color 同樣,來決定是否打開本地的鎖。
若是上述的兩個條件均知足,則執行更新本地棋盤、斷定輸贏、打開本地鎖的邏輯。
每次須要斷定輸贏的地方,若是能夠斷定輸贏,那麼都會走到遊戲退出邏輯。退出的邏輯分爲 2 個部分,第 1 個是給用戶提示,第 2 個是調用雲函數清空記錄。
第 1 個邏輯中用戶提示,須要斷定用戶勝負狀態:
第 2 個邏輯中清除記錄的緣由是爲了方便調試,對於真正的業務場景,通常不會刪除歷史數據,方便問題定位。同時,這也是一個越權操做,須要調用雲函數來實現。
更多雲開發使用技巧及 Serverless 行業動態,掃碼關注咱們~