feat: 新增关卡进度同步系统并优化UI显示

1.  新增GameEvent.STAGE_PROGRESS_UPDATE事件与关卡进度镜像逻辑
2.  在SingletonModuleComp中添加关卡进度VM层字段与同步方法
3.  重构MissionComp的UI显示逻辑,拆分计时与阶段显示
4.  更新mission.prefab的UI节点结构与数据绑定
5.  统一关卡进度更新的调用方式,替换直接赋值为专用方法
This commit is contained in:
pan
2026-09-11 11:17:35 +08:00
parent f6a1a99dc9
commit c04a357183
4 changed files with 614 additions and 229 deletions

View File

@@ -90,9 +90,12 @@ export class MissionComp extends CCComp {
/** 开始战斗按钮 */
@property(Node)
start_btn: Node = null!
/** 时间/回合数显示节点 */
@property(Node)
time_node: Node = null!
/** 战斗计时 Label(mm:ss) */
@property(Label)
time_label: Label = null!
/** 阶段/进度显示 Label("第 X 节" / 回合间倒计时) */
@property(Label)
phase_label: Label = null!
@property(Node)
tooltip: Node = null!
@@ -298,12 +301,8 @@ export class MissionComp extends CCComp {
let s = remainSecond % 60;
let str = `${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`;
if (str != this.lastTimeStr) {
if (this.time_node && this.time_node.isValid) {
const timeChild = this.time_node.getChildByName("time");
if (timeChild) {
const label = timeChild.getComponent(Label);
if (label) label.string = str;
}
if (this.time_label && this.time_label.isValid) {
this.time_label.string = str;
}
this.lastTimeStr = str;
}
@@ -332,14 +331,8 @@ export class MissionComp extends CCComp {
if (!force && remain === this.lastTimeSecond) return;
this.lastTimeSecond = remain;
if (this.time_node && this.time_node.isValid) {
const phaseNode = this.time_node.getChildByPath("Phase/Label");
if (phaseNode) {
const label = phaseNode.getComponent(Label);
if (label) {
label.string = `下一节 ${remain}s`;
}
}
if (this.phase_label && this.phase_label.isValid) {
this.phase_label.string = `下一节 ${remain}s`;
}
}
@@ -490,23 +483,18 @@ export class MissionComp extends CCComp {
}
// 更新阶段显示 UI
if (this.time_node && this.time_node.isValid) {
const phaseNode = this.time_node.getChildByPath("Phase/Label");
if (phaseNode) {
const label = phaseNode.getComponent(Label);
if (label) {
label.string = `第 ${getProgressText(this.currentChapter, this.currentStage, this.currentSection)} 节`;
}
if (this.phase_label && this.phase_label.isValid) {
this.phase_label.string = `第 ${getProgressText(this.currentChapter, this.currentStage, this.currentSection)} 节`;
// 阶段切换动感表现:只在进入战斗阶段跳动一下,让流程充满心流体验
if (targetPhase === MissionPhase.BattleStart) {
Tween.stopAllByTarget(this.time_node);
this.time_node.scale = v3(1, 1, 1);
tween(this.time_node)
.to(0.3, { scale: v3(1.2, 1.2, 1) }, { easing: "backOut" })
.to(0.2, { scale: v3(1, 1, 1) }, { easing: "sineInOut" })
.start();
}
// 阶段切换动感表现:只在进入战斗阶段跳动一下,让流程充满心流体验
if (targetPhase === MissionPhase.BattleStart) {
const labelNode = this.phase_label.node;
Tween.stopAllByTarget(labelNode);
labelNode.scale = v3(1, 1, 1);
tween(labelNode)
.to(0.3, { scale: v3(1.2, 1.2, 1) }, { easing: "backOut" })
.to(0.2, { scale: v3(1, 1, 1) }, { easing: "sineInOut" })
.start();
}
}
@@ -811,11 +799,11 @@ export class MissionComp extends CCComp {
// 存档直接推进到下一关第 1 小节(仅写存档,内存进度保留用于本局结算显示);
// 第 10 关通关即本章全通,存档停留等待后续章节扩展
if (this.currentStage < 10) {
smc.data.stage_progress = {
smc.updateStageProgress({
chapter: this.currentChapter,
stage: this.currentStage + 1,
section: 1,
};
});
if ((smc as any).updateCloudData) {
(smc as any).updateCloudData();
}
@@ -921,20 +909,22 @@ export class MissionComp extends CCComp {
this.currentStage = 1;
this.currentSection = 1;
}
// 加载完成后将权威进度镜像到 vmdata,驱动 HUD 实时显示
smc.syncStageProgressToView();
mLogger.log(this.debugMode, 'MissionComp',
`[StageProgress] 加载进度: ${getProgressText(this.currentChapter, this.currentStage, this.currentSection)}`);
}
/**
* 保存关卡进度存档
* 写入 smc.data.stage_progress,并标记云端同步
* 写入 smc.data.stage_progress 并镜像到 vmdata,同时标记云端同步
*/
private saveStageProgress() {
smc.data.stage_progress = {
smc.updateStageProgress({
chapter: this.currentChapter,
stage: this.currentStage,
section: this.currentSection,
};
});
// 标记数据脏,触发云端/本地同步
if ((smc as any).updateCloudData) {
(smc as any).updateCloudData();
@@ -1228,13 +1218,13 @@ export class MissionComp extends CCComp {
/** 性能监控相关代码 */
/** 初始化性能监控面板:在 time_node 下创建 Label */
/** 初始化性能监控面板:在本组件节点下创建 Label */
private initMemoryPanel() {
if (!this.showMemoryPanel || !this.time_node) return;
let panel = this.time_node.getChildByName("mem_panel");
if (!this.showMemoryPanel) return;
let panel = this.node.getChildByName("mem_panel");
if (!panel) {
panel = new Node("mem_panel");
panel.parent = this.time_node;
panel.parent = this.node;
panel.setPosition(0, -32, 0);
}
let label = panel.getComponent(Label);
@@ -1248,7 +1238,7 @@ export class MissionComp extends CCComp {
/** 移除性能监控面板 */
private removeMemoryPanel() {
const panel = this.time_node?.getChildByName("mem_panel");
const panel = this.node?.getChildByName("mem_panel");
if (panel) {
panel.destroy();
}