feat(结算界面): 添加MVP英雄展示功能
在战斗结算界面中,根据英雄等级和攻击力计算MVP(最厉害英雄),并渲染展示其卡牌信息。实现包括: - 新增MVP英雄评选逻辑 - 复用卡牌放大显示UI组件 - 加载并播放英雄闲置动画 - 动态调整卡牌尺寸和布局
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -18,7 +18,7 @@
|
|||||||
* - ScoreWeights(ScoreSet)—— 得分权重配置
|
* - ScoreWeights(ScoreSet)—— 得分权重配置
|
||||||
* - GameEvent.MissionEnd / MissionStart —— 游戏生命周期事件
|
* - GameEvent.MissionEnd / MissionStart —— 游戏生命周期事件
|
||||||
*/
|
*/
|
||||||
import { _decorator, instantiate, Label ,Prefab,Node} from "cc";
|
import { _decorator, instantiate, Label ,Prefab,Node, Sprite, Animation, AnimationClip, resources, UITransform, Widget } from "cc";
|
||||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||||
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
|
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
|
||||||
import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops";
|
import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops";
|
||||||
@@ -29,6 +29,8 @@ import { HeroAttrsComp } from "../hero/HeroAttrsComp";
|
|||||||
import { HeroViewComp } from "../hero/HeroViewComp";
|
import { HeroViewComp } from "../hero/HeroViewComp";
|
||||||
import { FacSet } from "../common/config/GameSet";
|
import { FacSet } from "../common/config/GameSet";
|
||||||
import { Attrs } from "../common/config/HeroAttrs";
|
import { Attrs } from "../common/config/HeroAttrs";
|
||||||
|
import { HeroInfo } from "../common/config/heroSet";
|
||||||
|
import { CKind } from "../common/config/CardSet";
|
||||||
import { ScoreWeights } from "../common/config/ScoreSet";
|
import { ScoreWeights } from "../common/config/ScoreSet";
|
||||||
import { mLogger } from "../common/Logger";
|
import { mLogger } from "../common/Logger";
|
||||||
|
|
||||||
@@ -91,6 +93,231 @@ export class VictoryComp extends CCComp {
|
|||||||
|
|
||||||
// 计算总分
|
// 计算总分
|
||||||
this.calculateTotalScore();
|
this.calculateTotalScore();
|
||||||
|
|
||||||
|
// 显示MVP英雄
|
||||||
|
const mvp = this.getMVPHero();
|
||||||
|
this.renderMVPHero(mvp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ======================== MVP 英雄 ========================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取战斗中最厉害的英雄(根据等级和攻击力)
|
||||||
|
*/
|
||||||
|
private getMVPHero(): HeroAttrsComp | null {
|
||||||
|
let mvp: HeroAttrsComp | null = null;
|
||||||
|
ecs.query(ecs.allOf(HeroAttrsComp)).forEach((entity: ecs.Entity) => {
|
||||||
|
const model = entity.get(HeroAttrsComp);
|
||||||
|
if (!model || model.fac !== FacSet.HERO) return;
|
||||||
|
if (!mvp) {
|
||||||
|
mvp = model;
|
||||||
|
} else {
|
||||||
|
if (model.lv > mvp.lv) {
|
||||||
|
mvp = model;
|
||||||
|
} else if (model.lv === mvp.lv && model.ap > mvp.ap) {
|
||||||
|
mvp = model;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return mvp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渲染 MVP 英雄,逻辑参考 CardComp 长按放大的 UI 显示
|
||||||
|
*/
|
||||||
|
private renderMVPHero(mvp: HeroAttrsComp | null) {
|
||||||
|
if (!this.mvp_node) return;
|
||||||
|
|
||||||
|
if (!mvp) {
|
||||||
|
this.mvp_node.active = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.mvp_node.active = true;
|
||||||
|
|
||||||
|
const uuid = mvp.hero_uuid;
|
||||||
|
const hero = HeroInfo[uuid];
|
||||||
|
if (!hero) return;
|
||||||
|
|
||||||
|
const kindName = CKind[CKind.Hero];
|
||||||
|
|
||||||
|
// 节点查找
|
||||||
|
const BG_node = this.mvp_node.getChildByName("BG");
|
||||||
|
const HF_node = this.mvp_node.getChildByName("HF");
|
||||||
|
const NF_node = this.mvp_node.getChildByName("NF");
|
||||||
|
const lv_node = this.mvp_node.getChildByName("lv");
|
||||||
|
const name_node = this.mvp_node.getChildByName("name");
|
||||||
|
const ap_node = this.mvp_node.getChildByName("ap");
|
||||||
|
const hp_node = this.mvp_node.getChildByName("hp");
|
||||||
|
const oinfo_node = this.mvp_node.getChildByName("oinfo");
|
||||||
|
const icon_node = this.mvp_node.getChildByName("icon");
|
||||||
|
const hbNode = this.mvp_node.getChildByName("HB");
|
||||||
|
const cost_node = this.mvp_node.getChildByName("cost");
|
||||||
|
|
||||||
|
// ---- 背景与边框 ----
|
||||||
|
if (BG_node) {
|
||||||
|
BG_node.children.forEach(child => {
|
||||||
|
child.active = (child.name === kindName);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HF_node) {
|
||||||
|
HF_node.active = true;
|
||||||
|
// HF_node.children.forEach(child => {
|
||||||
|
// child.active = (child.name === kindName);
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NF_node) {
|
||||||
|
NF_node.active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hbNode) hbNode.active = false;
|
||||||
|
|
||||||
|
// ---- 卡牌等级标识 ----
|
||||||
|
const cardLvStr = `lv${mvp.pool_lv || 1}`;
|
||||||
|
if (lv_node) {
|
||||||
|
lv_node.children.forEach(child => {
|
||||||
|
if (child.name === "light") {
|
||||||
|
child.active = false;
|
||||||
|
} else if (child.name === "bg") {
|
||||||
|
child.active = true;
|
||||||
|
} else {
|
||||||
|
child.active = (child.name === cardLvStr);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- 调整尺寸 (模拟放大状态) ----
|
||||||
|
const isEnlarged = true; // 结算界面的卡牌默认处于放大显示状态
|
||||||
|
const uiTrans = this.mvp_node.getComponent(UITransform);
|
||||||
|
if (uiTrans) {
|
||||||
|
uiTrans.setContentSize(isEnlarged ? 230 : 170, isEnlarged ? 340 : 230);
|
||||||
|
const widget = this.mvp_node.getComponent(Widget);
|
||||||
|
if (widget) widget.updateAlignment();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BG_node) {
|
||||||
|
const bgTrans = BG_node.getComponent(UITransform);
|
||||||
|
if (bgTrans) {
|
||||||
|
bgTrans.setContentSize(isEnlarged ? 230 : 170, isEnlarged ? 340 : 230);
|
||||||
|
const widget = BG_node.getComponent(Widget);
|
||||||
|
if (widget) widget.updateAlignment();
|
||||||
|
}
|
||||||
|
BG_node.children.forEach(child => {
|
||||||
|
const childTrans = child.getComponent(UITransform);
|
||||||
|
if (childTrans) {
|
||||||
|
childTrans.setContentSize(isEnlarged ? 230 : 170, isEnlarged ? 340 : 230);
|
||||||
|
const widget = child.getComponent(Widget);
|
||||||
|
if (widget) widget.updateAlignment();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HF_node) {
|
||||||
|
const hfTrans = HF_node.getComponent(UITransform);
|
||||||
|
if (hfTrans) {
|
||||||
|
hfTrans.setContentSize(isEnlarged ? 230 : 170, isEnlarged ? 340 : 230);
|
||||||
|
const widget = HF_node.getComponent(Widget);
|
||||||
|
if (widget) widget.updateAlignment();
|
||||||
|
}
|
||||||
|
HF_node.children.forEach(child => {
|
||||||
|
const childTrans = child.getComponent(UITransform);
|
||||||
|
if (childTrans) {
|
||||||
|
childTrans.setContentSize(isEnlarged ? 230 : 170, isEnlarged ? 340 : 230);
|
||||||
|
const widget = child.getComponent(Widget);
|
||||||
|
if (widget) widget.updateAlignment();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.mvp_node.children.forEach(child => {
|
||||||
|
const widget = child.getComponent(Widget);
|
||||||
|
if (widget) widget.updateAlignment();
|
||||||
|
child.children.forEach(subChild => {
|
||||||
|
const subWidget = subChild.getComponent(Widget);
|
||||||
|
if (subWidget) subWidget.updateAlignment();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ---- 文本信息 ----
|
||||||
|
const heroLv = mvp.lv || 1;
|
||||||
|
const suffix = heroLv >= 2 ? "★".repeat(heroLv - 1) : "";
|
||||||
|
if (name_node) {
|
||||||
|
const label = name_node.getComponent(Label);
|
||||||
|
if (label) label.string = `${suffix}${hero.name || ""}${suffix}`;
|
||||||
|
const currentPos = name_node.position;
|
||||||
|
name_node.setPosition(currentPos.x, isEnlarged ? 8 : -70, currentPos.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ap_node) {
|
||||||
|
ap_node.active = true;
|
||||||
|
const valNode = ap_node.getChildByName("val");
|
||||||
|
if (valNode) {
|
||||||
|
const label = valNode.getComponent(Label);
|
||||||
|
if (label) label.string = `${Math.floor(mvp.ap)}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hp_node) {
|
||||||
|
hp_node.active = true;
|
||||||
|
const valNode = hp_node.getChildByName("val");
|
||||||
|
if (valNode) {
|
||||||
|
const label = valNode.getComponent(Label);
|
||||||
|
if (label) label.string = `${Math.floor(mvp.hp_max)}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oinfo_node) {
|
||||||
|
oinfo_node.active = isEnlarged;
|
||||||
|
const infoLabel = oinfo_node.getChildByName("info")?.getComponent(Label);
|
||||||
|
if (infoLabel) infoLabel.string = `${hero.info || ""}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cost_node) {
|
||||||
|
cost_node.active = false; // 结算时不显示金币费用
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- 图标动画 ----
|
||||||
|
if (icon_node) {
|
||||||
|
this.updateHeroAnimation(icon_node, uuid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateHeroAnimation(node: Node, uuid: number) {
|
||||||
|
const sprite = node.getComponent(Sprite) || node.getComponentInChildren(Sprite);
|
||||||
|
if (sprite) sprite.spriteFrame = null;
|
||||||
|
|
||||||
|
const hero = HeroInfo[uuid];
|
||||||
|
if (!hero) return;
|
||||||
|
|
||||||
|
const anim = node.getComponent(Animation) || node.addComponent(Animation);
|
||||||
|
|
||||||
|
// clear animation clips
|
||||||
|
const clips = anim.clips;
|
||||||
|
for (let i = clips.length - 1; i >= 0; i--) {
|
||||||
|
const clip = clips[i];
|
||||||
|
if (clip) anim.removeClip(clip);
|
||||||
|
}
|
||||||
|
|
||||||
|
const path = `game/heros/hero/${hero.path}/idle`;
|
||||||
|
resources.load(path, AnimationClip, (err, clip) => {
|
||||||
|
if (err || !clip) {
|
||||||
|
mLogger.log(this.debugMode, "VictoryComp", `load hero animation failed ${uuid}`, err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// avoid state conflict
|
||||||
|
if (!this.node.isValid || !this.mvp_node || !this.mvp_node.active) return;
|
||||||
|
|
||||||
|
const currentClips = anim.clips;
|
||||||
|
for (let i = currentClips.length - 1; i >= 0; i--) {
|
||||||
|
const c = currentClips[i];
|
||||||
|
if (c) anim.removeClip(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
anim.addClip(clip);
|
||||||
|
anim.play("idle");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ======================== 得分计算 ========================
|
// ======================== 得分计算 ========================
|
||||||
|
|||||||
Reference in New Issue
Block a user