聊天功能是多人在线游戏最常见也是最基础的功能. Colyseus 内置了许多方便的工具用来实现多人在线游戏的信息互递.
而 Cocos Creator 作为游戏客户端可以方便地集成 Colyseus 提供的功能. 下面通过实现一个聊天室来展示 Colyseus 的迷人之处.

0_1630287798317_result.jpg

0_1630287809666_console.jpg

客户端 (Cocos Creator 3)

启动 Cocos Creator, 新建一个名为 "CocosColyseusChat" 的 2D 项目. 然后参考这篇文章开启 Colyseus 插件.
客户端由两个场景构成并且包含三个脚本.

场景

  • login 场景
    0_1630288403924_loginScene.jpg
    (点击打开大图)

    登录场景非常简单, 提示用户输入网名, 点击登录按钮. 场景脚本 loginScript 控制客户端节点 ClientNode 连接登入聊天服务器.
    需要注意的是 ClientNode 作为 Colyseus 客户端节点, 包含客户端控制脚本, 而且是各个场景公用的, 所以一开始就要将它列为持久节点.

        if (this.clientNode && !game.isPersistRootNode(this.clientNode))
            game.addPersistRootNode(this.clientNode);
    
  • room 场景
    0_1630289091897_roomScene.jpg
    (点击打开大图)
    聊天室场景分为大厅公屏和用户输入两个部分. 用户输入的信息通过 Colyseus 客户端发送至服务器然后广播给聊天室里的所有客户端 (包括自己), 并输出在公屏上.

脚本

  • clientScript
    ClientNode空节点上的脚本, 代表 Colyseus 客户端, 负责登录服务器, 发送和接收聊天消息.
async connect (userName:string="") {
        this.client = new Colyseus.Client(`${this.useSSL ? "wss" : "ws"}://${this.hostname}${([443, 80].includes(this.port) || this.useSSL) ? "" : `:${this.port}`}`);
        try {
            this.room = await this.client.joinOrCreate("lobby", {userName:userName});
            this.room.onMessage("messages", (message) => {
                this.node.emit("messages", message);
            });

        } catch (e) {
            console.error(e);
        }
    }

    send (message:string="")
    {
        this.room.send("message", message);
    }

关于 Colyseus 客户端的使用请参考官方文档.

  • loginScript
    登录场景使用的脚本. 确保用户输入网名之后才可以登录.
    if (this.nameBox.string.length>0 && !this.okButton.interactable)
        this.okButton.interactable = true;
    else if (this.nameBox.string.length == 0 && this.okButton.interactable)
        this.okButton.interactable = false;
  • roomScript
    聊天室场景使用的脚本, 负责聊天消息的接收和发送.
this.clientNode.on("messages", (message)=>{
            this.lobbyBox.string+=message+"\n";
        });
if (this.sendButton.interactable && this.messageBox.string.length>0)
        {
            this.sendButton.interactable = false;
            this.clientNode.getComponent<ClientScript>(ClientScript).send(this.messageBox.string);
            this.messageBox.string = "";
        }

服务端 (Colyseus)

Colyseus 内置了 LobbyRoom 这个大厅聊天室脚本, 是不是很贴心?
我们可以直接继承这个大厅脚本, 然后扩展它的功能. 比如, 把用户名存在客户端的 userData 里.

import {Client, LobbyRoom, Room} from "colyseus";

export class CocosLobbyRoom extends LobbyRoom {
    // this room supports only 4 clients connected
    maxClients = 4;

    // @ts-ignore
    onCreate (options: any): Promise<void> {
        console.log("ChatRoom created!", options);

        this.onMessage("message", (client, message) => {
            console.log("ChatRoom received message from", client.sessionId, ":", message);
            this.broadcast("messages", `(${client.userData}): ${message}`);
        });
    }

    onJoin (client: Client, options: any) {
        client.userData = options.userName;
        this.broadcast("messages", `${ client.userData } joined.`);
    }

    onLeave (client: Client) {
        this.broadcast("messages", `${ client.userData } left.`);
    }

    onDispose () {
        console.log("Dispose ChatRoom");
    }

}

到这里我们的聊天室就全部完成了, 当然商用时还需加入错误检查, 单词过滤等等功能, 这里为了简介起见就都省略了. 有兴趣可以自己尝试实现更多功能.
我们可以看到, 使用 Colyseus, 条理清晰, 逻辑明确, 短短几行代码就实现了从客户端到服务器的开发工作. 方便, 稳定, 扩展容易是 Colyseus 的特色.

开源地址

https://github.com/CocosGames/CocosColyseusChat/