你的第一个 Client Engine 小游戏 · Node.js
该文档帮助您快速上手,通过 Client Engine 实现一个剪刀石头布的猜拳小游戏。完成本文档教程后,您会对 Client Engine 的基础使用流程有初步的理解。
准备初始项目
这个小游戏分为服务端和客户端两部分,其中服务端使用 Client Engine 来实现,客户端则是一个简单的 Web 页面。在这个教程中我们着重教您一步一步写 Client Engine 中的代码,客户端的代码请您查看示例项目。
Client Engine 项目
请先阅读 Client Engine 快速入门:运行及部署项目 获得初始项目,了解如何本地运行及部署项目。
./src 中主要源文件及用途如下:
├── configs.ts // 配置文件
├── index.ts // 项目入口
├── reception.ts // Reception 类实现文件,GameManager 的子类,负责管理 Game,在这个文件中撰写了创建 Game 的自定义方法
└── rps-game.ts // RPSGame 类实现文件,Game 的子类,在这个文件中撰写了具体猜拳游戏的逻辑
该项目中的 Game 及 GameManager 使用的是 Client Engine SDK 的功能,关于 SDK 的详细用法请参考 Client Engine 开发指南。
您可以从 index.ts 文件入手来了解整个项目,该文件是项目启动的入口,它通过 express 框架定义了名为 /reservation 的 Web API,供客户端快速开始时为客户端下发新的房间名称。
reception.ts 及 rps-game.ts 里面有本教程的全部代码。您可以选择备份这两个文件,清空这两个文件后根据本文档撰写自己的代码,同时也可以查看已经写好的代码以做对比。
客户端项目
点击下载客户端项目。打开 ./src 中的 config.ts,将 appId 和 appKey 修改为自己应用的信息,按照 README 启动项目后观察界面的变化。游戏相关的逻辑位于 ./src/components 下的文件中,在有需要的时候您可以打开这里的文件查看代码。
核心流程
在多人对战服务中,房间的创建者为 MasterClient,因此在这个小游戏中,每一个房间都是由 Client Engine 管理的 MasterClient 调用在线对战服务相关的接口来创建的。Client Engine 中会有多个 MasterClient,每一个 MasterClient 管理着自己房间内的游戏逻辑。
这个小游戏的核心逻辑为:**Client Engine 中的 MasterClient 及客户端玩家 Client 加入到同一个房间,在通信过程中由 MasterClient 控制游戏内的逻辑。**具体拆解步骤如下:
- 玩家客户端连接多人在线对战服务,向 Client Engine 提供的
/reservation接口请求快速开始游戏。 - Client Engine 每次收到请求后会检查是否有可用的房间,如果有则返回已有的 roomName 给客户端;如果没有则创建新的 MasterClient 并创建一个新的房间,返回 roomName 给客户端。
- 客户端通过 Client Engine 返回的 roomName 加入房间。
- MasterClient 和客户端在同一房间内,每次客户端出拳时会将消息发送给 MasterClient,MasterClient 将消息转发给其他客户端,并最终判定游戏结果。
- MasterClient 判定游戏结束,客户端离开 房间,Client Engine 销毁游戏。
代码开发
自定义 Game
我们的目标是让 MasterClient 和客户端 Client 进入同一个房间,第一步在 Client Engine 中我们先准备好房间。在 Client Engine SDK 中,每一个房间都对应一个 Game 对象,每一个 Game 对象都对应一个自己的 MasterClient。接下来我们创建一个继承 Game 的子类 RPSGame ,在 RPSGame 中撰写猜拳小游戏的房间内逻辑。
在 rpg-game.ts 文件中初始化自定义的 RPSGame:
import { Game } from "@leancloud/client-engine";
import { Event, Play, Room } from "@leancloud/play";
export default class RPSGame extends Game {
constructor(room: Room, masterClient: Play) {
super(room, masterClient);
}
}