本文作者是声网社区的开发者“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("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 分钟使用额度。如在开发过程中遇到疑问,可在声网开发者社区与官方工程师交流。