From b88d3c214a84069ae81e8bcabcb09c3f1058312f Mon Sep 17 00:00:00 2001 From: walkpan Date: Fri, 27 Mar 2026 19:24:29 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E8=8B=B1=E9=9B=84?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E5=BC=B9=E7=AA=97=E6=98=BE=E7=A4=BA=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在卡牌点击时打开英雄技能信息弹窗 - 为英雄头像信息组件添加点击打开弹窗功能 - 重构信息弹窗组件,支持动态显示英雄技能信息 - 调整弹窗UI布局和尺寸以适应不同数量的技能显示 --- assets/resources/gui/element/ibox.prefab | 81 ++++++++++++-------- assets/script/game/map/CardComp.ts | 15 ++++ assets/script/game/map/HInfoComp.ts | 30 +++++++- assets/script/game/map/IBoxComp.ts | 94 +++++++++++++++++------- 4 files changed, 161 insertions(+), 59 deletions(-) diff --git a/assets/resources/gui/element/ibox.prefab b/assets/resources/gui/element/ibox.prefab index f5c9ef73..92ae5999 100644 --- a/assets/resources/gui/element/ibox.prefab +++ b/assets/resources/gui/element/ibox.prefab @@ -35,10 +35,13 @@ }, { "__id__": 122 + }, + { + "__id__": 124 } ], "_prefab": { - "__id__": 124 + "__id__": 126 }, "_lpos": { "__type__": "cc.Vec3", @@ -96,7 +99,7 @@ "_lpos": { "__type__": "cc.Vec3", "x": 0, - "y": 0, + "y": 125, "z": 0 }, "_lrot": { @@ -136,8 +139,8 @@ }, "_contentSize": { "__type__": "cc.Size", - "width": 660, - "height": 200 + "width": 700, + "height": 150 }, "_anchorPoint": { "__type__": "cc.Vec2", @@ -210,14 +213,14 @@ "__prefab": { "__id__": 8 }, - "_alignFlags": 45, + "_alignFlags": 18, "_target": null, - "_left": 0, - "_right": 0, - "_top": 0, - "_bottom": 0, + "_left": 330, + "_right": 330, + "_top": 610, + "_bottom": 610, "_horizontalCenter": 0, - "_verticalCenter": 0, + "_verticalCenter": 125, "_isAbsLeft": true, "_isAbsRight": true, "_isAbsTop": true, @@ -290,7 +293,7 @@ "_lpos": { "__type__": "cc.Vec3", "x": 0, - "y": 0, + "y": 125, "z": 0 }, "_lrot": { @@ -535,7 +538,7 @@ }, "_lpos": { "__type__": "cc.Vec3", - "x": -235, + "x": -230, "y": 0, "z": 0 }, @@ -576,7 +579,7 @@ }, "_contentSize": { "__type__": "cc.Size", - "width": 545, + "width": 535, "height": 50.4 }, "_anchorPoint": { @@ -721,7 +724,7 @@ }, "_contentSize": { "__type__": "cc.Size", - "width": 620, + "width": 610, "height": 40 }, "_anchorPoint": { @@ -1006,7 +1009,7 @@ }, "_lpos": { "__type__": "cc.Vec3", - "x": -235, + "x": -230, "y": 0, "z": 0 }, @@ -1047,7 +1050,7 @@ }, "_contentSize": { "__type__": "cc.Size", - "width": 545, + "width": 535, "height": 50.4 }, "_anchorPoint": { @@ -1192,7 +1195,7 @@ }, "_contentSize": { "__type__": "cc.Size", - "width": 620, + "width": 610, "height": 40 }, "_anchorPoint": { @@ -2682,7 +2685,7 @@ }, "_contentSize": { "__type__": "cc.Size", - "width": 660, + "width": 650, "height": 100 }, "_anchorPoint": { @@ -2708,14 +2711,14 @@ "__prefab": { "__id__": 114 }, - "_alignFlags": 45, + "_alignFlags": 18, "_target": null, - "_left": 0, - "_right": 0, - "_top": 50, - "_bottom": 50, + "_left": 310, + "_right": 310, + "_top": 590, + "_bottom": 590, "_horizontalCenter": 0, - "_verticalCenter": 0, + "_verticalCenter": 125, "_isAbsLeft": true, "_isAbsRight": true, "_isAbsTop": true, @@ -2797,8 +2800,8 @@ }, "_contentSize": { "__type__": "cc.Size", - "width": 660, - "height": 200 + "width": 720, + "height": 1280 }, "_anchorPoint": { "__type__": "cc.Vec2", @@ -2823,10 +2826,10 @@ "__prefab": { "__id__": 121 }, - "_alignFlags": 40, + "_alignFlags": 45, "_target": null, - "_left": 30, - "_right": 30, + "_left": 0, + "_right": 0, "_top": 0, "_bottom": 0, "_horizontalCenter": 0, @@ -2838,7 +2841,7 @@ "_isAbsHorizontalCenter": true, "_isAbsVerticalCenter": true, "_originalWidth": 100, - "_originalHeight": 0, + "_originalHeight": 200, "_alignMode": 2, "_lockFlags": 0, "_id": "" @@ -2880,6 +2883,24 @@ "__type__": "cc.CompPrefabInfo", "fileId": "caFlytW6dOyKuX32MnVcBt" }, + { + "__type__": "cc.BlockInputEvents", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 1 + }, + "_enabled": true, + "__prefab": { + "__id__": 125 + }, + "_id": "" + }, + { + "__type__": "cc.CompPrefabInfo", + "fileId": "a6TSZyZXZJl5pquoyibxvV" + }, { "__type__": "cc.PrefabInfo", "root": { diff --git a/assets/script/game/map/CardComp.ts b/assets/script/game/map/CardComp.ts index 6662958f..a6a680c8 100644 --- a/assets/script/game/map/CardComp.ts +++ b/assets/script/game/map/CardComp.ts @@ -9,6 +9,7 @@ import { SkillSet } from "../common/config/SkillSet"; import { GameEvent } from "../common/config/GameEvent"; import { oops } from "db://oops-framework/core/Oops"; import { smc } from "../common/SingletonModuleComp"; +import { UIID } from "../common/config/GameUIConfig"; @@ -317,6 +318,7 @@ export class CardComp extends CCComp { this.useCard(); return; } + this.openHeroInfoIBox(); this.playReboundAnim(); } @@ -467,6 +469,19 @@ export class CardComp extends CCComp { return `${uuid}`; } + private openHeroInfoIBox() { + if (!this.cardData) return; + if (this.cardData.type !== CardType.Hero) return; + const hero = HeroInfo[this.cardData.uuid]; + if (!hero) return; + const heroLv = Math.max(1, Math.floor(this.cardData.hero_lv ?? hero.lv ?? 1)); + oops.gui.remove(UIID.IBox); + oops.gui.open(UIID.IBox, { + heroUuid: this.cardData.uuid, + heroLv + }); + } + private updateHeroAnimation(node: Node, uuid: number, token: number) { const sprite = node?.getComponent(Sprite) || node?.getComponentInChildren(Sprite); if (sprite) sprite.spriteFrame = null; diff --git a/assets/script/game/map/HInfoComp.ts b/assets/script/game/map/HInfoComp.ts index caf7728c..d8ecf33f 100644 --- a/assets/script/game/map/HInfoComp.ts +++ b/assets/script/game/map/HInfoComp.ts @@ -1,8 +1,10 @@ -import { _decorator, Animation, AnimationClip, Label, Node, Sprite, resources } from "cc"; +import { _decorator, Animation, AnimationClip, Label, Node, NodeEventType, Sprite, resources } from "cc"; import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS"; import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp"; import { HeroInfo } from "../common/config/heroSet"; import { HeroAttrsComp } from "../hero/HeroAttrsComp"; +import { oops } from "db://oops-framework/core/Oops"; +import { UIID } from "../common/config/GameUIConfig"; const {property, ccclass } = _decorator; @@ -21,6 +23,11 @@ export class HInfoComp extends CCComp { onLoad() { this.cacheLabels(); + this.bindEvents(); + } + + onDestroy() { + this.unbindEvents(); } bindData(eid: number, model: HeroAttrsComp) { @@ -116,6 +123,27 @@ export class HInfoComp extends CCComp { [...clips].forEach(clip => anim.removeClip(clip, true)); } + private bindEvents() { + this.node.on(NodeEventType.TOUCH_END, this.onOpenIBox, this); + } + + private unbindEvents() { + this.node.off(NodeEventType.TOUCH_END, this.onOpenIBox, this); + } + + private onOpenIBox() { + if (!this.model) return; + const heroUuid = this.model.hero_uuid ?? 0; + if (!heroUuid || !HeroInfo[heroUuid]) return; + const heroLv = Math.max(1, Math.floor(this.model.lv ?? 1)); + oops.gui.remove(UIID.IBox); + oops.gui.open(UIID.IBox, { + heroUuid, + heroLv, + skills: this.model.skills + }); + } + /** 视图对象通过 ecs.Entity.remove(ModuleViewComp) 删除组件是触发组件处理自定义释放逻辑 */ reset() { this.clearIconAnimation(this.icon_node); diff --git a/assets/script/game/map/IBoxComp.ts b/assets/script/game/map/IBoxComp.ts index ca2be215..3b72eb42 100644 --- a/assets/script/game/map/IBoxComp.ts +++ b/assets/script/game/map/IBoxComp.ts @@ -1,25 +1,13 @@ -import { mLogger } from "../common/Logger"; -import { _decorator, Animation, AnimationClip, EventTouch, Label, Node, NodeEventType, Sprite, SpriteAtlas, Tween, tween, UIOpacity, Vec3, resources } from "cc"; +import { _decorator, Label, Node, UITransform } from "cc"; import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS"; import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp"; -import { CardConfig, CardType, SpecialCardList } from "../common/config/CardSet"; -import { CardUseComp } from "./CardUseComp"; import { HeroInfo } from "../common/config/heroSet"; import { SkillSet } from "../common/config/SkillSet"; -import { GameEvent } from "../common/config/GameEvent"; -import { oops } from "db://oops-framework/core/Oops"; -import { smc } from "../common/SingletonModuleComp"; - - - const { ccclass, property } = _decorator; -/** 视图层对象 */ @ccclass('IBoxComp') @ecs.register('IBoxComp', false) export class IBoxComp extends CCComp { - private debugMode: boolean = true; - /** 锁定态图标节点(显示时表示本槽位锁定) */ @property(Node) Line1: Node = null! @property(Node) @@ -30,24 +18,74 @@ export class IBoxComp extends CCComp { Line4: Node = null! @property(Node) Line5: Node = null! - onAdded(args: any) { - + private readonly baseHeight: number = 100; + private readonly extraLineHeight: number = 50; + + onAdded(args: { + heroUuid?: number; + heroLv?: number; + skills?: Record; + }) { + this.renderHeroInfo(args); } - onLoad() { - - - } - - onDestroy() { - } - init(){ - } - - - - /** 视图对象通过 ecs.Entity.remove(ModuleViewComp) 删除组件是触发组件处理自定义释放逻辑 */ reset() { this.node.destroy(); } + + private renderHeroInfo(args: { + heroUuid?: number; + heroLv?: number; + skills?: Record; + }) { + const heroUuid = Math.floor(args?.heroUuid ?? 0); + const heroLv = Math.max(1, Math.floor(args?.heroLv ?? 1)); + const hero = HeroInfo[heroUuid]; + if (!hero) { + this.applyLineTexts(["暂无技能信息"]); + return; + } + const runtimeSkills = args?.skills ? Object.values(args.skills) : []; + const sourceSkills = runtimeSkills.length > 0 ? runtimeSkills : Object.values(hero.skills ?? {}); + const skillTexts = sourceSkills.map(skill => { + const skillId = Math.floor(skill?.uuid ?? 0); + if (!skillId) return ""; + const config = SkillSet[skillId]; + if (!config) return ""; + const runtimeLv = runtimeSkills.length > 0 ? Math.max(0, Math.floor(skill.lv ?? 0)) : Math.max(0, Math.floor((skill.lv ?? 1) + heroLv - 2)); + const cd = Number(skill?.cd ?? 0); + return `${config.name} Lv.${runtimeLv} CD:${cd}s ${config.info}`; + }).filter(Boolean); + this.applyLineTexts(skillTexts.length > 0 ? skillTexts : ["暂无技能信息"]); + } + + private applyLineTexts(skillTexts: string[]) { + const lines = [this.Line1, this.Line2, this.Line3, this.Line4, this.Line5]; + const showCount = Math.max(1, Math.min(lines.length, skillTexts.length)); + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + if (!line) continue; + const active = i < showCount; + line.active = active; + if (!active) continue; + const text = skillTexts[i] ?? ""; + const noteNode = line.getChildByName("note"); + const label = noteNode?.getComponent(Label) || noteNode?.getComponentInChildren(Label) || line.getComponentInChildren(Label); + if (label) label.string = text; + } + const targetHeight = this.baseHeight + Math.max(0, showCount - 1) * this.extraLineHeight; + this.updateIBoxHeight(targetHeight); + } + + private updateIBoxHeight(height: number) { + const rootTransform = this.node.getComponent(UITransform); + if (rootTransform) { + rootTransform.setContentSize(rootTransform.contentSize.width, height); + } + const bgNode = this.node.getChildByName("Bg"); + const bgTransform = bgNode?.getComponent(UITransform); + if (bgTransform) { + bgTransform.setContentSize(bgTransform.contentSize.width, height); + } + } }