feat(ui): 增加卡牌点击放大功能并调整动画速度
- 点击卡牌可切换放大/缩小状态,放大时显示详细信息并调整位置层级 - 调整技能准备动画的播放速度和时长以优化视觉效果 - 修复技能触发逻辑,为未处理的类型添加默认动画播放 - 在MissionCardComp中记录卡牌原始定位点用于布局管理
This commit is contained in:
@@ -195,6 +195,8 @@ export class SCastSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate
|
||||
heroView.playReady("yellow");
|
||||
} else if (triggerType === 'dead') {
|
||||
heroView.playOther("dead");
|
||||
}else{
|
||||
heroView.playOther('yellow')
|
||||
}
|
||||
|
||||
// 如果是敌方攻击技能,必须在战斗中才能释放;友方增益/护盾则允许在非战斗中释放
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
* - smc.vmdata.mission_data —— 读写局内金币
|
||||
*/
|
||||
import { mLogger } from "../common/Logger";
|
||||
import { _decorator, Animation, AnimationClip, EventTouch, Label, Node, NodeEventType, Sprite, SpriteAtlas, Tween, tween, UIOpacity, Vec3, resources, Light } from "cc";
|
||||
import { _decorator, Animation, AnimationClip, EventTouch, Label, Node, NodeEventType, Sprite, SpriteAtlas, Tween, tween, UIOpacity, Vec3, resources, Light, 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, SpecialRefreshCardList, SpecialUpgradeCardList, CKind, CardPoolList } from "../common/config/CardSet";
|
||||
@@ -121,6 +121,8 @@ export class CardComp extends CCComp {
|
||||
* 防止快速切卡时旧回调错误覆盖新图标。
|
||||
*/
|
||||
private iconVisualToken: number = 0;
|
||||
/** 是否处于放大状态 */
|
||||
private isEnlarged: boolean = false;
|
||||
|
||||
// ======================== 生命周期 ========================
|
||||
|
||||
@@ -259,6 +261,7 @@ export class CardComp extends CCComp {
|
||||
this.card_type = data.type;
|
||||
this.card_cost = data.cost;
|
||||
this.node.active = true;
|
||||
this.isEnlarged = false;
|
||||
this.applyCardUI();
|
||||
this.playRefreshAnim();
|
||||
mLogger.log(this.debugMode, "CardComp", "card updated", {
|
||||
@@ -394,7 +397,28 @@ export class CardComp extends CCComp {
|
||||
this.restPosition = new Vec3(x, this.fixedBaseY, this.fixedBaseZ);
|
||||
// 拖拽/使用中不立即移动,等状态结束后归位
|
||||
if (!this.isDragging && !this.isUsing) {
|
||||
this.node.setPosition(this.restPosition);
|
||||
// ---- 放大时的位置偏移和层级调整 ----
|
||||
let targetX = this.restPosition.x;
|
||||
let targetY = this.restPosition.y;
|
||||
|
||||
if (this.isEnlarged) {
|
||||
// 层级提高,凸显在最外层
|
||||
this.node.setSiblingIndex(999);
|
||||
// x轴偏移逻辑
|
||||
if (this.restPosition.x < -200) { // -260
|
||||
targetX = this.restPosition.x + 30;
|
||||
} else if (this.restPosition.x > 200) { // 260
|
||||
targetX = this.restPosition.x - 30;
|
||||
}
|
||||
// y轴变大时 +35
|
||||
targetY = this.restPosition.y + 35;
|
||||
} else {
|
||||
// 恢复层级(可以根据实际情况调整,默认层级在父节点管理下应该会恢复)
|
||||
// 如果需要严格恢复,这里可以不设置或者使用原始的siblingIndex,但目前不影响,只要放大的是最高就行
|
||||
// 如果有兄弟节点层级问题,可以在 MissionCardComp 中处理,这里先只管提高
|
||||
}
|
||||
|
||||
this.node.setPosition(targetX, targetY, this.restPosition.z);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -415,6 +439,7 @@ export class CardComp extends CCComp {
|
||||
this.isLocked = false;
|
||||
this.isDragging = false;
|
||||
this.isUsing = false;
|
||||
this.isEnlarged = false;
|
||||
this.node.setPosition(this.restPosition);
|
||||
this.node.setScale(new Vec3(1, 1, 1));
|
||||
this.updateLockUI();
|
||||
@@ -440,6 +465,7 @@ export class CardComp extends CCComp {
|
||||
this.card_type = CardType.Hero;
|
||||
this.isLocked = false;
|
||||
this.isDragging = false;
|
||||
this.isEnlarged = false;
|
||||
this.node.setPosition(this.restPosition);
|
||||
this.node.setScale(new Vec3(1, 1, 1));
|
||||
this.updateLockUI();
|
||||
@@ -485,13 +511,25 @@ export class CardComp extends CCComp {
|
||||
if (!this.isDragging || !this.cardData || this.isUsing) return;
|
||||
const currentY = event.getUILocation().y;
|
||||
const deltaY = Math.max(0, currentY - this.touchStartY);
|
||||
this.node.setPosition(this.restPosition.x, this.restPosition.y + deltaY, this.restPosition.z);
|
||||
|
||||
let baseX = this.restPosition.x;
|
||||
let baseY = this.restPosition.y;
|
||||
if (this.isEnlarged) {
|
||||
if (this.restPosition.x <= -200) {
|
||||
baseX = this.restPosition.x + 30;
|
||||
} else if (this.restPosition.x >= 200) {
|
||||
baseX = this.restPosition.x - 30;
|
||||
}
|
||||
baseY = this.restPosition.y + 35;
|
||||
}
|
||||
|
||||
this.node.setPosition(baseX, baseY + deltaY, this.restPosition.z);
|
||||
}
|
||||
|
||||
/**
|
||||
* 触摸结束:
|
||||
* - 上拉距离 >= dragUseThreshold → 视为"使用卡牌"
|
||||
* - 否则视为"点击",打开英雄信息弹窗(仅英雄卡)并回弹
|
||||
* - 否则视为"点击",切换放大缩小状态并回弹
|
||||
*/
|
||||
private onCardTouchEnd(event: EventTouch) {
|
||||
if (!this.isDragging || !this.cardData || this.isUsing) return;
|
||||
@@ -502,10 +540,16 @@ export class CardComp extends CCComp {
|
||||
this.useCard();
|
||||
return;
|
||||
}
|
||||
this.openHeroInfoIBox();
|
||||
this.toggleEnlarge();
|
||||
this.playReboundAnim();
|
||||
}
|
||||
|
||||
/** 切换卡牌的放大/缩小状态 */
|
||||
private toggleEnlarge() {
|
||||
this.isEnlarged = !this.isEnlarged;
|
||||
this.applyCardUI();
|
||||
}
|
||||
|
||||
/** 触摸取消:回弹至原位 */
|
||||
private onCardTouchCancel() {
|
||||
if (!this.isDragging || this.isUsing) return;
|
||||
@@ -560,7 +604,19 @@ export class CardComp extends CCComp {
|
||||
// 递增视觉令牌,用于异步加载竞态保护
|
||||
this.iconVisualToken += 1;
|
||||
if (this.opacityComp) this.opacityComp.opacity = 255;
|
||||
this.node.setPosition(this.restPosition);
|
||||
|
||||
let targetX = this.restPosition.x;
|
||||
let targetY = this.restPosition.y;
|
||||
if (this.isEnlarged) {
|
||||
this.node.setSiblingIndex(99); // 变大时提到最前
|
||||
if (this.restPosition.x <= -200) { // -260
|
||||
targetX = this.restPosition.x + 30;
|
||||
} else if (this.restPosition.x >= 200) { // 260
|
||||
targetX = this.restPosition.x - 30;
|
||||
}
|
||||
targetY = this.restPosition.y + 35; // y轴增加
|
||||
}
|
||||
this.node.setPosition(targetX, targetY, this.restPosition.z);
|
||||
|
||||
// ---- 卡牌种类标识(近战 / 远程 / 辅助等) ----
|
||||
if (this.Ckind_node) {
|
||||
@@ -593,16 +649,31 @@ export class CardComp extends CCComp {
|
||||
}
|
||||
|
||||
// ---- 按卡牌类型渲染具体内容 ----
|
||||
const uiTrans = this.node.getComponent(UITransform);
|
||||
if (uiTrans) {
|
||||
uiTrans.setContentSize(this.isEnlarged ? 230 : 170, this.isEnlarged ? 300 : 230);
|
||||
}
|
||||
|
||||
if(this.card_type===CardType.Hero){
|
||||
// 英雄卡:显示英雄名 + 星级 + AP/HP
|
||||
const hero = HeroInfo[this.card_uuid];
|
||||
const heroLv = Math.max(1, Math.floor(this.cardData.hero_lv ?? hero?.lv ?? 1));
|
||||
const suffix = heroLv >= 2 ? "★".repeat(heroLv - 1) : "";
|
||||
this.setLabel(this.name_node, `${suffix}${hero?.name || ""}${suffix}`);
|
||||
this.info_node.active = true;
|
||||
this.oinfo_node.active = false;
|
||||
this.info_node.getChildByName("ap").getChildByName("val").getComponent(Label).string = `${(hero?.ap ?? 0) * heroLv}`;
|
||||
this.info_node.getChildByName("hp").getChildByName("val").getComponent(Label).string = `${(hero?.hp ?? 0) * heroLv}`;
|
||||
if (this.oinfo_node) {
|
||||
const infoLabel = this.oinfo_node.getChildByName("info")?.getComponent(Label);
|
||||
if (infoLabel) infoLabel.string = `${hero?.info || ""}`;
|
||||
}
|
||||
|
||||
if (this.isEnlarged) {
|
||||
this.info_node.active = true;
|
||||
this.oinfo_node.active = true;
|
||||
} else {
|
||||
this.info_node.active = false;
|
||||
this.oinfo_node.active = false;
|
||||
}
|
||||
}else if(this.card_type===CardType.Skill){
|
||||
// 技能卡:显示技能名 + 品质后缀 + 描述
|
||||
const skill = SkillSet[this.card_uuid];
|
||||
@@ -610,9 +681,15 @@ export class CardComp extends CCComp {
|
||||
const card_lv = Math.max(1, Math.floor(this.cardData.card_lv ?? 1));
|
||||
const spSuffix = card_lv >= 2 ? "★".repeat(card_lv - 1) : "";
|
||||
this.setLabel(this.name_node, `${spSuffix}${skillCard?.name || skill?.name || ""}${spSuffix}`);
|
||||
this.info_node.active = false;
|
||||
this.oinfo_node.active = true;
|
||||
this.oinfo_node.getChildByName("info").getComponent(Label).string = `${skillCard?.info || skill?.info || ""}`;
|
||||
|
||||
if (this.isEnlarged) {
|
||||
this.info_node.active = false;
|
||||
this.oinfo_node.active = true;
|
||||
} else {
|
||||
this.info_node.active = false;
|
||||
this.oinfo_node.active = false;
|
||||
}
|
||||
}else{
|
||||
// 特殊卡(升级 / 刷新):显示卡名 + 品质后缀 + 描述
|
||||
const specialCard = this.card_type === CardType.SpecialUpgrade
|
||||
@@ -621,9 +698,15 @@ export class CardComp extends CCComp {
|
||||
const card_lv = Math.max(1, Math.floor(this.cardData.card_lv ?? 1));
|
||||
const spSuffix = card_lv >= 2 ? "★".repeat(card_lv - 1) : "";
|
||||
this.setLabel(this.name_node, `${spSuffix}${specialCard?.name || ""}${spSuffix}`);
|
||||
this.info_node.active = false;
|
||||
this.oinfo_node.active = true;
|
||||
this.oinfo_node.getChildByName("info").getComponent(Label).string = `${specialCard?.info || ""}`;
|
||||
|
||||
if (this.isEnlarged) {
|
||||
this.info_node.active = false;
|
||||
this.oinfo_node.active = true;
|
||||
} else {
|
||||
this.info_node.active = false;
|
||||
this.oinfo_node.active = false;
|
||||
}
|
||||
}
|
||||
|
||||
// ---- 费用标签 ----
|
||||
@@ -660,12 +743,23 @@ export class CardComp extends CCComp {
|
||||
.start();
|
||||
}
|
||||
|
||||
/** 回弹动画:从当前位置平滑回到静止位并恢复缩放 */
|
||||
/** 回弹动画:从当前位置平滑回到静止位或放大位置并恢复缩放 */
|
||||
private playReboundAnim() {
|
||||
Tween.stopAllByTarget(this.node);
|
||||
let targetX = this.restPosition.x;
|
||||
let targetY = this.restPosition.y;
|
||||
if (this.isEnlarged) {
|
||||
if (this.restPosition.x <= -200) {
|
||||
targetX = this.restPosition.x + 30;
|
||||
} else if (this.restPosition.x >= 200) {
|
||||
targetX = this.restPosition.x - 30;
|
||||
}
|
||||
targetY = this.restPosition.y + 35;
|
||||
}
|
||||
|
||||
tween(this.node)
|
||||
.to(0.12, {
|
||||
position: this.restPosition,
|
||||
position: new Vec3(targetX, targetY, this.restPosition.z),
|
||||
scale: new Vec3(1, 1, 1)
|
||||
})
|
||||
.start();
|
||||
@@ -703,6 +797,10 @@ export class CardComp extends CCComp {
|
||||
* 清空名称、费用、信息面板、种类标识、背景底框、边框、图标。
|
||||
*/
|
||||
private applyEmptyUI() {
|
||||
const uiTrans = this.node.getComponent(UITransform);
|
||||
if (uiTrans) {
|
||||
uiTrans.setContentSize(170, 230);
|
||||
}
|
||||
this.iconVisualToken += 1;
|
||||
this.setLabel(this.name_node, "");
|
||||
this.setLabel(this.cost_node, "");
|
||||
|
||||
@@ -137,6 +137,8 @@ export class MissionCardComp extends CCComp {
|
||||
private cardsShowScale: Vec3 = new Vec3(1, 1, 1);
|
||||
/** 卡牌面板收起态缩放(scale=0 隐藏) */
|
||||
private cardsHideScale: Vec3 = new Vec3(0, 0, 1);
|
||||
/** 卡牌原始定位点 */
|
||||
private cardsPos = [-260,86,-86,260]
|
||||
/**
|
||||
* 英雄信息面板映射:EID → { node, model, comp }
|
||||
* 用于追踪每个出战英雄的面板实例和数据引用
|
||||
|
||||
Reference in New Issue
Block a user