组件系统代码示例
组件模式适用于服务端及客户端。
本文档提供了使用 @dao3fun/component
组件系统的各种实用示例,帮助创作者快速掌握组件的创建、挂载和通信方式。
单组件示例
以下示例展示了如何创建一个简单的广播组件,挂载后指定实体会发送欢迎消息。
typescript
import { Component, EntityNode, _decorator } from "@dao3fun/component";
const { apclass } = _decorator;
/**
* @SayComponent - 实体广播组件
*/
@apclass("SayComponent")
class SayComponent extends Component<GameEntity> {
start(): void {
this.node.entity.say(`欢迎你`);
}
}
const e = world.querySelector("#实体名称");
if (e) {
const node = new EntityNode(e);
node.addComponent(SayComponent);
}
组件初始参数配置
组件可以通过构造函数的参数进行初始化,实现组件的配置化。以下示例展示了如何通过配置参数初始化组件。
typescript
import { Component, EntityNode, _decorator } from "@dao3fun/component";
const { apclass } = _decorator;
/**
* @SayComponent - 实体广播组件
*/
@apclass("SayComponent")
class SayComponent extends Component<GameEntity> {
say = "ap";
start(): void {
console.log("SayComponent 说:", this.say);
}
}
const e = world.querySelector("#实体名字-1");
if (e) {
const node = new EntityNode(e);
node.addComponent(SayComponent, {
say: "hello",
});
}
组件性能事件监听
以下示例展示了如何全局监听组件的性能事件,例如帧率过低。
typescript
import { Component, EntityNode, _decorator } from "@dao3fun/component";
const { apclass } = _decorator;
/**
* @SayComponent - 实体广播组件
*/
@apclass("SayComponent")
class SayComponent extends Component<GameEntity> {
start(): void {
this.node.entity.say(`欢迎你`);
}
async update(deltaTime: number): Promise<void> {
console.log("update");
await sleep(1000);
}
}
const e = world.querySelector("#实体名称");
if (e) {
const node = new EntityNode(e);
node.addComponent(SayComponent);
}
// 开启全局性能监控
EntityNode.isMonitoringEnabled = true;
// 注册全局性能警告回调
EntityNode.onPerformanceWarning(({ entityNode, component, currentFPS }) => {
console.warn(
`实体 ${entityNode.entity.id} 的组件${component.constructor.name}帧率过低: ${currentFPS}`
);
});
节点实例获取
通过 find
方法可以获取已绑定到节点上的实体实例。注意:只有已经通过 EntityNode
绑定的实体才能被找到。
typescript
import { EntityNode, find } from "@dao3fun/component";
const e = world.querySelector("#实体名称-1");
const e2 = world.querySelector("#实体名称-2");
if (e && e2) {
new EntityNode(e);
console.log(find(e)?.entity.id); // 输出: 实体名称-1
console.log(find(e2)?.entity.id); // 输出: undefined (因为e2未绑定到节点)
}
多组件挂载示例
一个实体可以挂载多个组件,每个组件负责不同的功能。以下示例展示了如何同时挂载广播和跳跃组件。
typescript
import { Component, EntityNode, _decorator } from "@dao3fun/component";
const { apclass } = _decorator;
/**
* @SayComponent - 实体广播组件
*/
@apclass("SayComponent")
class SayComponent extends Component<GameEntity> {
start(): void {
GameWorldEvent.on(world.onPlayerJoin, this.onWechat, this);
}
onDestroy(): void {
GameWorldEvent.off(world.onPlayerJoin, this.onWechat, this);
}
private onWechat({ entity }: GamePlayerEntityEvent): void {
// 让游戏中的实体说欢迎词,欢迎新加入游戏的玩家
this.node.entity.say(`欢迎${entity.player.name}加入游戏`);
}
}
/**
* @CaperComponent - 物理跳跃组件
*/
@apclass("CaperComponent")
class CaperComponent extends Component<GameEntity> {
start(): void {
this.node.entity.velocity.y++;
}
}
const e = world.querySelector("#实体名称");
if (e) {
const node = new EntityNode(e);
node.addComponent(SayComponent);
node.addComponent(CaperComponent);
}
单节点组件间通信
同一节点上的不同组件可以通过事件系统进行通信,实现组件间的解耦合。
typescript
import { Component, EntityNode, _decorator } from "@dao3fun/component";
const { apclass } = _decorator;
/**
* @SayComponent - 实体广播组件
*/
@apclass("SayComponent")
class SayComponent extends Component<GameEntity> {
start(): void {
this.node.on("say", this.log, this);
}
protected log(text: string): void {
console.log(text);
}
}
/**
* @SayMgrComponent - 实体广播管理组件
*/
@apclass("SayMgrComponent")
class SayMgrComponent extends Component<GameEntity> {
start(): void {
this.node.emit("say", "hello world,来自SayMgrComponent", this);
}
}
const e = world.querySelector("#实体名称");
if (e) {
const node = new EntityNode(e);
node.addComponent(SayComponent);
node.addComponent(SayMgrComponent);
}
多节点组件间通信
不同节点上的组件可以通过全局事件系统进行通信,实现跨节点的消息传递。
typescript
import { Component, EntityNode, Emitter, _decorator } from "@dao3fun/component";
const { apclass } = _decorator;
/**
* @SayComponent - 实体广播组件
*/
@apclass("SayComponent")
class SayComponent extends Component<GameEntity> {
start(): void {
Emitter.on("say", this.log, this);
}
protected log(text: string): void {
console.log(text);
}
}
/**
* @SayMgrComponent - 实体广播管理组件
*/
@apclass("SayMgrComponent")
class SayMgrComponent extends Component<GameEntity> {
start(): void {
Emitter.emit("say", "hello world,来自SayMgrComponent");
}
}
const e = world.querySelector("#实体名称-1");
const e2 = world.querySelector("#实体名称-2");
if (e && e2) {
const node2 = new EntityNode(e2);
node2.addComponent(SayComponent);
const node = new EntityNode(e);
node.addComponent(SayMgrComponent);
}
组件继承示例
通过组件继承,可以复用父组件的功能并扩展新的行为。以下示例展示了如何通过继承实现功能扩展。
typescript
import { Component, EntityNode, _decorator } from "@dao3fun/component";
const { apclass } = _decorator;
/**
* @CaperComponent - 物理跳跃组件
*/
@apclass("CaperComponent")
class CaperComponent extends Component<GameEntity> {
jump() {
this.node.entity.velocity.y++;
}
}
/**
* @SayComponent - 实体广播跳跃组件
*/
@apclass("SayComponent")
class SayComponent extends CaperComponent {
start(): void {
this.jump();
}
}
const e = world.querySelector("#实体名称");
if (e) {
const node = new EntityNode(e);
node.addComponent(SayComponent);
}
计时器组件示例
以下示例展示了如何创建一个计时器组件,可以用于管理游戏中的定时事件。
typescript
import { Component, EntityNode, _decorator } from "@dao3fun/component";
const { apclass } = _decorator;
/**
* @TimerComponent - 计时器组件
*/
@apclass("TimerComponent")
class TimerComponent extends Component<GameEntity> {
private timeElapsed = 0;
private readonly interval = 1000; // 1秒间隔
update(deltaTime: number): void {
this.timeElapsed += deltaTime;
if (this.timeElapsed >= this.interval) {
this.timeElapsed = 0;
this.onTimerTick();
}
}
private onTimerTick(): void {
this.node.entity.say("又过去了1秒!");
}
}
const e = world.querySelector("#计时器实体");
if (e) {
const node = new EntityNode(e);
node.addComponent(TimerComponent);
}
资源管理组件示例
创建一个管理游戏资源(如分数、生命值等)的组件。
typescript
import { Component, EntityNode, _decorator } from "@dao3fun/component";
const { apclass } = _decorator;
/**
* @ResourceComponent - 资源管理组件
*/
@apclass("ResourceComponent")
class ResourceComponent extends Component<GameEntity> {
private health = 100;
private score = 0;
private coins = 0;
start(): void {
Emitter.on("damage", this.takeDamage, this);
Emitter.on("collect", this.collectItem, this);
}
private takeDamage(amount: number): void {
this.health = Math.max(0, this.health - amount);
this.node.entity.say(`受到伤害!剩余生命值:${this.health}`);
if (this.health <= 0) {
Emitter.emit("gameOver", this.score);
}
}
private collectItem(type: string, value: number): void {
switch (type) {
case "coin":
this.coins += value;
this.score += value * 10;
this.node.entity.say(`收集金币!当前分数:${this.score}`);
break;
case "health":
this.health = Math.min(100, this.health + value);
this.node.entity.say(`恢复生命值!当前生命值:${this.health}`);
break;
}
}
}
const e = world.querySelector("#实体名称");
if (e) {
const node = new EntityNode(e);
node.addComponent(ResourceComponent);
// 测试资源系统
setTimeout(() => {
Emitter.emit("damage", 20);
}, 1000);
setTimeout(() => {
Emitter.emit("collect", "coin", 5);
}, 3000);
setTimeout(() => {
Emitter.emit("collect", "health", 30);
}, 5000);
}
简单日志系统
这个系统在每次添加或移除实体节点时记录日志,适合用于调试和监控实体的变化。
typescript
class LoggingSystem extends NodeSystem {
protected onEntityNodeAdded(entityNode: EntityNode): void {
console.log(`实体节点 ${entityNode.id} 已添加到系统`);
}
protected onEntityNodeRemoved(entityNode: EntityNode): void {
console.log(`实体节点 ${entityNode.id} 已从系统移除`);
}
}
简单计时器系统
这个系统在每帧更新时增加一个计时器,适合用于需要时间跟踪的场景。
typescript
class TimerSystem extends NodeSystem {
private elapsedTime: number = 0;
protected update(deltaTime: number): void {
this.elapsedTime += deltaTime;
console.log(`系统运行时间:${this.elapsedTime} 毫秒`);
}
}
物理更新系统
这个系统用于更新实体的物理状态,比如位置和速度,适合用于简单的物理模拟。
typescript
class PhysicsSystem extends NodeSystem {
protected update(deltaTime: number): void {
for (const entity of this.entities) {
const physicsComponent = entity.getComponent("PhysicsComponent");
if (physicsComponent) {
physicsComponent.updatePhysics(deltaTime);
}
}
}
}
碰撞检测系统
这个系统用于检测实体之间的碰撞,并触发相应的事件,适合用于游戏中的碰撞处理。
typescript
class CollisionDetectionSystem extends NodeSystem {
protected update(deltaTime: number): void {
const entities = this.entities;
for (let i = 0; i < entities.length; i++) {
for (let j = i + 1; j < entities.length; j++) {
if (this.checkCollision(entities[i], entities[j])) {
entities[i].emit("collision", entities[j]);
entities[j].emit("collision", entities[i]);
}
}
}
}
private checkCollision(entity1: EntityNode, entity2: EntityNode): boolean {
// 简单的碰撞检测逻辑
return Math.random() > 0.5; // 示例逻辑
}
}
AI 控制系统
这个系统用于管理和更新实体的 AI 行为,适合用于复杂的游戏 AI 控制。
typescript
class AISystem extends NodeSystem {
protected update(deltaTime: number): void {
for (const entity of this.entities) {
const aiComponent = entity.getComponent("AIComponent");
if (aiComponent) {
aiComponent.updateAI(deltaTime);
}
}
}
}