96 lines
3.0 KiB
TypeScript
96 lines
3.0 KiB
TypeScript
import { _decorator, NodePool, Node, Label, Color, tween, Vec3, instantiate, Prefab, resources } from "cc";
|
|
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
|
import { DamageResult } from "./DamageComp";
|
|
import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops";
|
|
import { DamageText } from "./DamageText";
|
|
|
|
@ecs.register('DamageShowSystem')
|
|
export class DamageShowSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate{
|
|
private _pool: NodePool = new NodePool();
|
|
private _timers: Set<number> = new Set();
|
|
private _prefab: Prefab | null = null;
|
|
|
|
init() {
|
|
// 使用原生资源加载
|
|
resources.load("game/skills/damageText", Prefab, (err, prefab) => {
|
|
if (err) {
|
|
console.error("预制体加载失败:", err);
|
|
return;
|
|
}
|
|
this._prefab = prefab;
|
|
console.log("预制体加载成功:", this._prefab);
|
|
// 初始化对象池
|
|
for (let i = 0; i < 10; i++) {
|
|
const node = instantiate(this._prefab!);
|
|
this._pool.put(node);
|
|
}
|
|
});
|
|
}
|
|
|
|
filter(): ecs.IMatcher {
|
|
return ecs.allOf(DamageResult);
|
|
}
|
|
|
|
update(e: ecs.Entity) {
|
|
const res = e.get(DamageResult);
|
|
this.scheduleShow(res);
|
|
e.remove(DamageResult);
|
|
}
|
|
|
|
private scheduleShow(res: DamageResult) {
|
|
const timer = setTimeout(() => {
|
|
let node = this._pool.get();
|
|
if (!node || !node.isValid) {
|
|
node = instantiate(this._prefab);
|
|
}
|
|
|
|
const damageText = node.getComponent(DamageText);
|
|
|
|
if (!damageText) {
|
|
console.error("Damage text prefab must have DamageText component!");
|
|
return;
|
|
}
|
|
|
|
this.setupText(node, res);
|
|
this.playAnimation(node, res.position);
|
|
|
|
this._timers.delete(timer);
|
|
}, res.delay * 1000);
|
|
|
|
this._timers.add(timer);
|
|
}
|
|
|
|
private setupText(node: Node, res: DamageResult) {
|
|
const damageText = node.getComponent(DamageText)!;
|
|
const label = damageText.label;
|
|
|
|
if (res.isDodged) {
|
|
label.string = "Miss";
|
|
label.color = Color.GRAY;
|
|
return;
|
|
}
|
|
|
|
label.string = Math.round(res.value).toString();
|
|
label.color = res.isCrit ? Color.RED : Color.WHITE;
|
|
damageText.playEffect(res.isCrit);
|
|
}
|
|
|
|
private playAnimation(node: Node, position: Vec3) {
|
|
node.setPosition(position);
|
|
tween(node)
|
|
.by(0.5, { position: new Vec3(0, 100, 0) })
|
|
.call(() => {
|
|
if (this._pool.size() < 20) { // 控制最大缓存数量
|
|
this._pool.put(node);
|
|
} else {
|
|
node.destroy();
|
|
}
|
|
})
|
|
.start();
|
|
}
|
|
|
|
onDestroy() {
|
|
this._timers.forEach(clearTimeout);
|
|
this._pool.clear();
|
|
}
|
|
}
|