如何基於開源 demo 在 Web 端實現一個多人數獨遊戲

語言: CN / TW / HK

本文作者是聲網社區的開發者“tjss”。他基於Vue、聲網的互動白板的代碼模板,搭建出了一個支持多人互動的數獨遊戲。本文記錄了他的實現過程,歡迎大家也可以嘗試實現自己的小遊戲或應用。

我基於聲網互動白板的 SDK 與 Window Manager 開發了一個場景化窗口插件,實現了一個多人數獨遊戲。在遊戲中,每個玩家進入白板房間,都能看到數獨遊戲插件,同時可以參與其中,與房間內的小夥伴一起完成數獨解題。

前期準備

1、註冊一個聲網賬號,並實名認證,以便在後台創建項目,獲取開發時會用到的 Appid 和 Token

2、瞭解 Vue 開發的基礎知識。

3、瞭解聲網互動白板產品,一些基本的接口和功能,看官方文檔就足夠了。

4、搭建開發環境:

  • NodeJs 版本 16.0.0

  • @Vue/cli 4.5.1

  • VSCode 代碼開發工具

開啟和配置互動白板服務

首先我們需要一個實名認證的聲網賬號,進入控制枱(console.agora.io),在聲網控制枱開啟互動白板服務。

這裏需要注意的是互動白板是作為服務而顯示的,而控制枱中只是顯示項目列表,並沒有直接顯示服務。

這時候我們就先創建一個項目,然後點擊“配置”進入到項目詳情中,在裏面的頁面就可以看到服務內容了。

這時候找到互動白板服務,點擊開啟就行。因為我的已經開啟了,所以顯示的是配置按鈕。

使用官網提供的代碼模板

場景化窗口插件目前我們不需要從零開始建立的,聲網提供了一個代碼模板,基於此模板我們可以很輕鬆就能實現一個在互動白板上使用的插件。

模板地址:https://github.com/netless-io/community-app-template

當搭建好開發環境後,便可以下載模板代碼了,通過 Git 或者下載 Zip 都行。

需要注意 README.md 中的開發環境配置:

1、在 .env 文件裏配置白板房間 UUID 和 Token請將本目錄下的 .env.example 文件複製一份,重命名為 .env 或 .env.local 後,在裏面填寫必須的白板配置信息。你可以在聲網互動白板官方的 Netless Workshop 申請專用的白板配置。

2、執行 npm install 安裝依賴

3、執行 npm start 進行本地開發

項目結構

筆者是基於 Vue 版本的插件模板進行開發的,直接打開項目,修改 src 裏的內容即可,基本上和 Vue 開發一致。如果是通過 Git 命令拉取的代碼,需要切換分支為 Vue 分支。

  • 項目結構如下:

  • playground 目錄是基本不用修改的,我們實現的插件是在 src 目錄中完成的。

  • index.ts 文件是我們插件的一些數據設置,比如插件名稱。其他邏輯基本不用修改。

onst Sudoku: NetlessApp = {
  kind: "Sudoku",
  setup(context) {
    const box = context.getBox();
    box.mountStyles(styles);
    const $content = document.createElement("div");
    $content.className = "app-counter";
    box.mountContent($content);
    const app = createApp(App).provide("context", context);
    app.mount($content);
    context.emitter.on("destroy", () => {
      app.unmount();
    });
  },
};
export default Sudoku;

數獨遊戲規則

數獨網格由 9x9 個空格組成。玩家只能使用數字 1 到 9,每個 3×3 宮只能包含數字 1 到 9,每一列只能包含數字 1 到 9,每一行只能包含數字 1 到 9,每個 3×3 宮、每一列或每一行中的每個數字只能使用一次。當所有數獨網格都填入正確的數字時,遊戲結束。(摘自網上)

數據同步核心思路

1、通過互動白板SDK提供的 createStorage 方法,初始化一個數獨棋盤,並把數據存儲起來,同時需要更新自己的 chessBoard。

const chessBoard = ref();
const context = inject<AppContext>("context");
const storage = context.createStorage("chessBoard", { chessBoard: ChessBoard.init() });
chessBoard.value = deepCopy(storage.state.chessBoard)

2、在 Vue 界面的 onMounted 回調函數中添加存儲值的更新監聽,這樣玩家在填格子的時候廣播了最新的格子數據,其他玩家就能收到更新的通知,然後重新渲染界面。

onMounted(() => {
  initAppData()
  storage.addStateChangedListener((diff) => {
    chessBoard.value = deepCopy(diff.chessBoard?.newValue)
    if (finish(chessBoard.value.gridItems)) {
      statistics(chessBoard.value.gridItems)
      finishTag.value = true
    }
  })
});

3、填格子的時候,通過 SDK 的 setState 方法去更新數獨棋盤的數據。

if (e.data && e.data > 0) {
    grid.number = parseInt(e.data)
    grid.userId = uid.value
    grid.color = rgb
  } else {
    grid.number = 0
    grid.userId = ''
    grid.color = new Rgb(233, 233, 233)
  }
  storage.setState({ chessBoard: chessBoard.value })

數獨遊戲界面

筆者是優先實現這個互動遊戲的核心功能,所以設計出的遊戲界面比較簡陋。

數獨的數據結構

export class ChessBoard {
    gridItems: GridItem[][]
}

因為需要統計遊戲結束後,各個玩家填寫的個數,所以在更新格子數值的時候也記錄一下是哪一位玩家填寫了。default 字段表示該格子是自動生成的,不需要玩家填寫了。

export class GridItem {
    number: number
    color: Rgb
    userId: string
    default: boolean
}

運行項目

點擊工具欄最下方的按鈕,可以找到我們實現的插件icon,然後點擊即可打開。

打開插件後,會初始化創建一個數獨題目,並且通過 createStorage 方法儲存起來,所有進入房間的玩家都能拿到這個數據,後續數獨的更新都會同步給玩家去修改。因為這個項目重點是學習一下插件開發與數據同步,所以遊戲界面以及內容這些做的比較簡單。

接下來就要打開多個網頁並且輸入 localhost:3000 進入我們的互動白板房間了,因為模板的uid是隨機生成的,也就表示有不同的玩家進入了。

別的玩家填寫後,其他玩家是不能再填這個格子的,最後遊戲結束的時候,會統計各個玩家所填對的數字並展示。

遊戲結束

總結

通過官方提供的場景化插件模板,我們很容易實現一些好玩的互動場景的功能。在這個簡單的項目中,由於時間倉促,還沒來得及優化得更好,後續有時間的時候筆者再打磨一下。比如不同玩家填寫的數字以不同的顏色區分,增加限時機制等等。感興趣的朋友一起來開發一些好玩的實時互動功能吧~

現註冊聲網賬號下載 SDK,可獲得每月免費 10000 分鐘使用額度。如在開發過程中遇到疑問,可在聲網開發者社區與官方工程師交流。