refactor: 重构关卡战斗流程与AI逻辑,改为单场Boss战模式
1. 近战AI新增警戒线机制,无威胁时退回编队 2. 替换多回合波次为单场Boss战,简化刷怪与回合逻辑 3. 重构招募系统为开局免费三选一流程 4. 调整英雄与怪物基础属性平衡 5. 精简HUD与配置文件冗余代码
This commit is contained in:
@@ -1,101 +1,74 @@
|
||||
/**
|
||||
* @file WaveHudComp.ts
|
||||
* @description 波次进度 HUD 组件(表现层)
|
||||
* @description 战斗进度 HUD 组件(表现层)
|
||||
*
|
||||
* 职责:
|
||||
* 1. 本回合清剿进度:剩余怪数(mon_num + pending_mon_num)+ 进度条。
|
||||
* 2. 全局 20 回合进度格:静态生成,Boss 回合(wave%5==0)置旗帜样式,当前回合脉动、已过回合置灰。
|
||||
* 1. 清剿进度:剩余怪数(mon_num + pending_mon_num)+ 进度条。
|
||||
* 2. Boss 战旗帜:单场 Boss 战定胜负,仅 1 格旗帜,战斗中脉动。
|
||||
*
|
||||
* 数据流:NewWave 事件缓存 total/wave;update 0.2s 降频轮询 vmdata(与 syncMonsterSpawnState 同节奏)。
|
||||
* 使用 oops-framework 模块:oops.message(事件解耦)。
|
||||
*
|
||||
* 编辑器绑定:waveLab / remainLab / progress / flagsRoot(水平 Layout 容器,20 格代码生成)。
|
||||
* 编辑器绑定: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";
|
||||
import { getWaveType, WaveType, MAX_WAVE } from "./RogueConfig";
|
||||
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
@ccclass('WaveHudComp')
|
||||
export class WaveHudComp extends CCComp {
|
||||
@property({ type: Label, tooltip: "回合文本(第 x/20 回合)" })
|
||||
@property({ type: Label, tooltip: "战斗标题文本" })
|
||||
waveLab: Label | null = null;
|
||||
|
||||
@property({ type: Label, tooltip: "剩余怪数文本" })
|
||||
remainLab: Label | null = null;
|
||||
|
||||
@property({ type: ProgressBar, tooltip: "本回合清剿进度条" })
|
||||
@property({ type: ProgressBar, tooltip: "清剿进度条" })
|
||||
progress: ProgressBar | null = null;
|
||||
|
||||
@property({ type: Node, tooltip: "全局回合旗帜容器(水平 Layout,20 格代码生成)" })
|
||||
@property({ type: Node, tooltip: "Boss 战旗帜容器(水平 Layout,1 格代码生成)" })
|
||||
flagsRoot: Node | null = null;
|
||||
|
||||
/** 本回合怪物总数(NewWave 事件载荷缓存) */
|
||||
/** 本场怪物总数(NewWave 事件载荷缓存) */
|
||||
private waveTotal: number = 0;
|
||||
/** HUD 刷新节流计时器 */
|
||||
private hudTimer: number = 0;
|
||||
/** 20 格旗帜节点缓存(Boss 位为旗帜样式) */
|
||||
private flagNodes: Node[] = [];
|
||||
/** Boss 战旗帜节点 */
|
||||
private flagNode: Node | null = null;
|
||||
|
||||
onLoad() {
|
||||
// oops.message 全局事件总线:新回合
|
||||
// oops.message 全局事件总线:新战斗
|
||||
oops.message.on(GameEvent.NewWave, this.onNewWave, this);
|
||||
this.buildFlags();
|
||||
this.buildFlag();
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
oops.message.off(GameEvent.NewWave, this.onNewWave, this);
|
||||
}
|
||||
|
||||
/** 静态生成 20 格回合进度(Boss 位按 getWaveType 静态预知,无需运行数据) */
|
||||
private buildFlags() {
|
||||
/** 静态生成 1 格 Boss 战旗帜 */
|
||||
private buildFlag() {
|
||||
if (!this.flagsRoot) return;
|
||||
for (let i = 1; i <= MAX_WAVE; i++) {
|
||||
const cell = new Node(`flag_${i}`);
|
||||
cell.addComponent(UITransform).setContentSize(14, 14);
|
||||
const sp = cell.addComponent(Sprite);
|
||||
// Boss 位用警示色方块,普通位用圆点色(无美术资源时以颜色区分,后续可换 spriteFrame)
|
||||
const isBoss = getWaveType(i) === WaveType.Pressure;
|
||||
sp.color = isBoss ? new Color(220, 50, 50) : new Color(120, 120, 120);
|
||||
sp.sizeMode = Sprite.SizeMode.CUSTOM;
|
||||
cell.parent = this.flagsRoot;
|
||||
this.flagNodes.push(cell);
|
||||
}
|
||||
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 = `第 ${data.wave}/${MAX_WAVE} 回合`;
|
||||
this.refreshFlags(data.wave);
|
||||
if (this.waveLab) this.waveLab.string = "最终 Boss 战";
|
||||
if (this.flagNode) this.playFlagPulse(this.flagNode);
|
||||
}
|
||||
|
||||
/** 刷新旗帜状态:已过回合置暗,当前回合 Boss 旗脉动 */
|
||||
private refreshFlags(currentWave: number) {
|
||||
for (let i = 0; i < this.flagNodes.length; i++) {
|
||||
const cell = this.flagNodes[i];
|
||||
const wave = i + 1;
|
||||
const sp = cell.getComponent(Sprite)!;
|
||||
const isBoss = getWaveType(wave) === WaveType.Pressure;
|
||||
if (wave < currentWave) {
|
||||
sp.color = new Color(70, 70, 70); // 已过回合置暗
|
||||
cell.setScale(v3(1, 1, 1));
|
||||
Tween.stopAllByTarget(cell);
|
||||
} else if (wave === currentWave) {
|
||||
sp.color = isBoss ? new Color(255, 80, 80) : new Color(255, 220, 100);
|
||||
if (isBoss) this.playFlagPulse(cell);
|
||||
} else {
|
||||
sp.color = isBoss ? new Color(220, 50, 50) : new Color(120, 120, 120);
|
||||
cell.setScale(v3(1, 1, 1));
|
||||
Tween.stopAllByTarget(cell);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 当前回合 Boss 旗缩放脉动 */
|
||||
/** Boss 战旗帜缩放脉动 */
|
||||
private playFlagPulse(cell: Node) {
|
||||
Tween.stopAllByTarget(cell);
|
||||
tween(cell)
|
||||
|
||||
Reference in New Issue
Block a user