Files
pixelheros/assets/script/game/map/WaveHudComp.ts
panFD c27c81cfa6 refactor: 重构关卡战斗流程与AI逻辑,改为单场Boss战模式
1.  近战AI新增警戒线机制,无威胁时退回编队
2.  替换多回合波次为单场Boss战,简化刷怪与回合逻辑
3.  重构招募系统为开局免费三选一流程
4.  调整英雄与怪物基础属性平衡
5.  精简HUD与配置文件冗余代码
2026-08-13 00:21:54 +08:00

97 lines
3.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @file WaveHudComp.ts
* @description 战斗进度 HUD 组件(表现层)
*
* 职责:
* 1. 清剿进度剩余怪数mon_num + pending_mon_num+ 进度条。
* 2. Boss 战旗帜:单场 Boss 战定胜负,仅 1 格旗帜,战斗中脉动。
*
* 数据流NewWave 事件缓存 total/waveupdate 0.2s 降频轮询 vmdata与 syncMonsterSpawnState 同节奏)。
* 使用 oops-framework 模块oops.message事件解耦
*
* 编辑器绑定waveLab / remainLab / progress / flagsRoot水平 Layout 容器1 格代码生成)。
*/
import { _decorator, Node, Label, ProgressBar, Sprite, Color, tween, Tween, v3, UITransform } from "cc";
import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops";
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
import { GameEvent } from "../common/config/GameEvent";
import { smc } from "../common/SingletonModuleComp";
const { ccclass, property } = _decorator;
@ccclass('WaveHudComp')
export class WaveHudComp extends CCComp {
@property({ type: Label, tooltip: "战斗标题文本" })
waveLab: Label | null = null;
@property({ type: Label, tooltip: "剩余怪数文本" })
remainLab: Label | null = null;
@property({ type: ProgressBar, tooltip: "清剿进度条" })
progress: ProgressBar | null = null;
@property({ type: Node, tooltip: "Boss 战旗帜容器(水平 Layout1 格代码生成)" })
flagsRoot: Node | null = null;
/** 本场怪物总数NewWave 事件载荷缓存) */
private waveTotal: number = 0;
/** HUD 刷新节流计时器 */
private hudTimer: number = 0;
/** Boss 战旗帜节点 */
private flagNode: Node | null = null;
onLoad() {
// oops.message 全局事件总线:新战斗
oops.message.on(GameEvent.NewWave, this.onNewWave, this);
this.buildFlag();
}
onDestroy() {
oops.message.off(GameEvent.NewWave, this.onNewWave, this);
}
/** 静态生成 1 格 Boss 战旗帜 */
private buildFlag() {
if (!this.flagsRoot) return;
const cell = new Node("flag_boss");
cell.addComponent(UITransform).setContentSize(14, 14);
const sp = cell.addComponent(Sprite);
sp.color = new Color(220, 50, 50);
sp.sizeMode = Sprite.SizeMode.CUSTOM;
cell.parent = this.flagsRoot;
this.flagNode = cell;
}
private onNewWave(event: string, data: { wave: number; total: number; bossWave: boolean }) {
this.waveTotal = data.total;
if (this.waveLab) this.waveLab.string = "最终 Boss 战";
if (this.flagNode) this.playFlagPulse(this.flagNode);
}
/** Boss 战旗帜缩放脉动 */
private playFlagPulse(cell: Node) {
Tween.stopAllByTarget(cell);
tween(cell)
.to(0.5, { scale: v3(1.4, 1.4, 1) })
.to(0.5, { scale: v3(1, 1, 1) })
.union()
.repeatForever()
.start();
}
protected update(dt: number) {
this.hudTimer += dt;
if (this.hudTimer < 0.2) return;
this.hudTimer = 0;
const md = smc.vmdata.mission_data;
const remain = (md.mon_num || 0) + (md.pending_mon_num || 0);
if (this.remainLab) this.remainLab.string = `剩余 ${remain}`;
if (this.progress) {
this.progress.progress = this.waveTotal > 0
? Math.min(1, Math.max(0, (this.waveTotal - remain) / this.waveTotal))
: 0;
}
}
}