feat(victory): 添加得分条和亮点标签的渲染逻辑
在 VictoryComp 中新增 renderScores 和 renderHighlights 方法,用于在结算界面展示各维度得分进度条和基于游戏数据的成就标签。同时添加了对应的 highlight.prefab 资源作为标签的 UI 模板。 - renderScores 方法渲染总分及各维度(战斗、输出、防御等)的得分条。 - renderHighlights 方法根据本局数据(如暴击次数、死亡触发次数等)匹配并生成最多3个亮点成就标签。 - 新增 highlight.prefab 作为标签的 UI 预制体,包含图标和文本。
This commit is contained in:
@@ -119,6 +119,9 @@ export class VictoryComp extends CCComp {
|
||||
|
||||
// 计算总分
|
||||
this.calculateTotalScore();
|
||||
|
||||
// 渲染分数UI和亮点标签
|
||||
this.renderScores();
|
||||
|
||||
// 显示MVP英雄
|
||||
const mvp = this.getMVPHero();
|
||||
@@ -397,6 +400,91 @@ export class VictoryComp extends CCComp {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 渲染得分条与亮点标签
|
||||
* 依赖各维度对应的UI节点(需要在Cocos Creator中拖入绑定)
|
||||
*/
|
||||
private renderScores() {
|
||||
const s = smc.vmdata.scores;
|
||||
|
||||
// 渲染总分
|
||||
if (this.total_score_label) {
|
||||
this.total_score_label.string = `${s.score}`;
|
||||
}
|
||||
|
||||
// 通用渲染单个维度的函数
|
||||
const renderDim = (node: Node, score: number, maxScore: number) => {
|
||||
if (!node) return;
|
||||
const lab = node.getChildByName("score_label")?.getComponent(Label);
|
||||
if (lab) lab.string = `${score}`;
|
||||
|
||||
const bar = node.getChildByName("progress_bar")?.getComponent(Sprite);
|
||||
if (bar) {
|
||||
// 根据该维度得分占“预期满分”的比例设置进度条(fillRange)
|
||||
bar.fillRange = Math.min(1, Math.max(0, score / maxScore));
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: 进度条的最大值可按设计期望自行调整,目前为占位预估值
|
||||
renderDim(this.combat_node, s.score_combat, 3000);
|
||||
renderDim(this.output_node, s.score_output, 3000);
|
||||
renderDim(this.defense_node, s.score_defense, 1500);
|
||||
renderDim(this.build_node, s.score_build, 1000);
|
||||
renderDim(this.efficiency_node, s.score_efficiency, 200);
|
||||
|
||||
// 渲染成就亮点标签
|
||||
this.renderHighlights();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据当前局数据匹配并生成对应的亮点标签(成就)
|
||||
*/
|
||||
private renderHighlights() {
|
||||
if (!this.highlights_container || !this.highlight_prefab) return;
|
||||
|
||||
// 先清空原有的标签
|
||||
this.highlights_container.removeAllChildren();
|
||||
|
||||
const s = smc.vmdata.scores;
|
||||
const tags: { name: string, desc: string }[] = [];
|
||||
|
||||
// 按照 scoring-system.md 设计的触发条件判定
|
||||
if (s.crt_count >= 40) tags.push({ name: "🔥 暴击大师", desc: `暴击${s.crt_count}次` });
|
||||
if (s.dead_trigger_count >= 25) tags.push({ name: "💀 送死达人", desc: `死亡触发${s.dead_trigger_count}次` });
|
||||
if (s.shield_block_count >= 30) tags.push({ name: "🛡️ 铁壁铜墙", desc: `格挡${s.shield_block_count}次` });
|
||||
if (s.wf_count >= 20) tags.push({ name: "⚡ 风暴之王", desc: `风怒${s.wf_count}次` });
|
||||
if (s.highest_dmg >= 200) tags.push({ name: "🎯 一击必杀", desc: `单次伤害${Math.floor(s.highest_dmg)}` });
|
||||
if (s.heal_total >= 500) tags.push({ name: "💊 治愈之光", desc: `治疗总量${Math.floor(s.heal_total)}` });
|
||||
|
||||
// 🏆 完美通关:通关且20回合全员存活
|
||||
if (s.passed_wave_20 && s.wave_all_alive_count >= 20) {
|
||||
tags.push({ name: "🏆 完美通关", desc: "20回合全胜" });
|
||||
}
|
||||
|
||||
// 效率类判定
|
||||
const refreshRatio = s.refresh_count > 0 ? (s.refresh_hit_count / s.refresh_count) : 0;
|
||||
if (refreshRatio >= 0.8) {
|
||||
tags.push({ name: "🎲 欧皇附体", desc: `刷新命中率${Math.floor(refreshRatio * 100)}%` });
|
||||
}
|
||||
|
||||
const goldRatio = s.gold_earned > 0 ? (s.gold_spent / s.gold_earned) : 0;
|
||||
if (goldRatio >= 0.95) {
|
||||
tags.push({ name: "💰 节俭玩家", desc: `金币使用率${Math.floor(goldRatio * 100)}%` });
|
||||
}
|
||||
|
||||
// 最多显示前3个亮点
|
||||
const displayTags = tags.slice(0, 3);
|
||||
displayTags.forEach(tag => {
|
||||
const tagNode = instantiate(this.highlight_prefab);
|
||||
// 尝试获取自身或者名为 "label" 的子节点上的 Label 组件
|
||||
const lab = tagNode.getComponent(Label) || tagNode.getChildByName("label")?.getComponent(Label);
|
||||
if (lab) {
|
||||
lab.string = `${tag.name} (${tag.desc})`;
|
||||
}
|
||||
this.highlights_container.addChild(tagNode);
|
||||
});
|
||||
}
|
||||
|
||||
// ======================== 操作入口 ========================
|
||||
|
||||
/** 退出战斗:清理数据 → 触发任务结束 → 关闭弹窗 */
|
||||
|
||||
Reference in New Issue
Block a user