最佳实践和建议¶
本文档正在编辑中
此文档页面可能不完整
本节提供一般建议和最佳惯例, 以确保您的代码库对您的团队来说是健康和可读的. 这些建议和最佳惯例都是可选的, 如果遵循它们, 将提高代码的可读性和整洁性.
- 您的房间应尽可能保持低等级, 而将特定于游戏的功能委托给其他可组合结构.
- 可同步的数据结构应尽可能较小
- 理想情况下, 每个扩展
Schema
的类应该只有字段定义. - 可以实现自定义 getter 和 setter 方法,只要其中没有游戏逻辑即可.
- 理想情况下, 每个扩展
- 应该由其他结构处理游戏逻辑, 例如:
单元测试¶
TODO: 我们需要提供一个
@colyseus/testing
包, 以轻松模拟Room
类, 并触发其生命周期事件, 以及创建虚拟客户端.
设计模式¶
命令模式¶
為什麼?
- 模型 (
@colyseus/schema
) 应主要包含数据, 而不包含复杂的游戏逻辑. - 房间代码应尽可能少, 并将动作转移到其他结构
命令模式具有多项优势, 例如:
- 它将调用操作的类与知道如何执行操作的对象进行分离.
- 它允许通过提供队列系统来创建命令序列.
- 很容易实现扩展以添加新命令,无需更改现有代码即可完成.
- 严格控制调用命令的方式和时间.
- 提高代码可读性和单元测试可能性.
用法¶
安装
npm install --save @colyseus/command
在房间实现中初始化 dispatcher
:
import { Room } from "colyseus";
import { Dispatcher } from "@colyseus/command";
import { OnJoinCommand } from "./OnJoinCommand";
class MyRoom extends Room<YourState> {
dispatcher = new Dispatcher(this);
onCreate() {
this.setState(new YourState());
}
onJoin(client, options) {
this.dispatcher.dispatch(new OnJoinCommand(), {
sessionId: client.sessionId
});
}
onDispose() {
this.dispatcher.stop();
}
}
const colyseus = require("colyseus");
const command = require("@colyseus/command");
const { OnJoinCommand } = require("./OnJoinCommand");
class MyRoom extends colyseus.Room {
onCreate() {
this.dispatcher = new command.Dispatcher(this);
this.setState(new YourState());
}
onJoin(client, options) {
this.dispatcher.dispatch(new OnJoinCommand(), {
sessionId: client.sessionId
});
}
onDispose() {
this.dispatcher.stop();
}
}
命令实现看起来是这样的:
// OnJoinCommand.ts
import { Command } from "@colyseus/command";
export class OnJoinCommand extends Command<MyRoom, {
sessionId: string
}> {
execute({ sessionId }) {
this.state.players[sessionId] = new Player();
}
}
// OnJoinCommand.js
const command = require("@colyseus/command");
exports.OnJoinCommand = class OnJoinCommand extends command.Command {
execute({ sessionId }) {
this.state.players[sessionId] = new Player();
}
}
参阅更多¶
- 参考 command definitions
- 参考 用法
- 参考 implementation
实体组件系统 (ECS)¶
目前我们没有正式的 ECS(实体组件系统),尽管我们已经看到社区成员实现了他们自己的解决方案.
试验中的功能