feat(map): 为三类商店卡牌组件添加动画交互效果
1. 新增按钮按下/取消缩放反馈、点击回弹动画 2. 新增卡牌入场淡入放大、购买放大淡出、刷新缩小淡出动画 3. 优化卡片切换逻辑,支持按状态播放对应动画 4. 同步重构了ItemListComp、EquipListComp、SCardComp三个组件 5. 删除了废弃的装备预制体元数据文件
This commit is contained in:
@@ -12,7 +12,7 @@
|
||||
* EquipBoxComp 按 Field 类型被动驻场,属性加成由 FieldSkillHelper 全局聚合。
|
||||
*/
|
||||
import { mLogger } from "../common/Logger";
|
||||
import { _decorator, Node, Sprite, Label, NodeEventType } from "cc";
|
||||
import { _decorator, Node, Sprite, Label, NodeEventType, Vec3, UIOpacity, tween, Tween } 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 } from "../common/config/CardSet";
|
||||
@@ -74,17 +74,28 @@ export class EquipListComp extends CCComp {
|
||||
private cardData: CardConfig | null = null;
|
||||
/** 是否已购买 */
|
||||
private isPurchased: boolean = false;
|
||||
/** 透明度组件(用于淡入淡出动画) */
|
||||
private opacityComp: UIOpacity | null = null;
|
||||
/** 入场动画时长(秒) */
|
||||
private readonly enterDuration: number = 0.25;
|
||||
/** 购买/逝去动画时长(秒) */
|
||||
private readonly exitDuration: number = 0.2;
|
||||
|
||||
// ======================== 生命周期 ========================
|
||||
|
||||
onLoad() {
|
||||
this.buy_node?.on(NodeEventType.TOUCH_START, this.onBuyTouchStart, this);
|
||||
this.buy_node?.on(NodeEventType.TOUCH_END, this.onBuyClick, this);
|
||||
this.buy_node?.on(NodeEventType.TOUCH_CANCEL, this.onBuyTouchCancel, this);
|
||||
this.opacityComp = this.node.getComponent(UIOpacity) || this.node.addComponent(UIOpacity);
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
super.onDestroy();
|
||||
if (this.buy_node && this.buy_node.isValid) {
|
||||
this.buy_node.off(NodeEventType.TOUCH_START, this.onBuyTouchStart, this);
|
||||
this.buy_node.off(NodeEventType.TOUCH_END, this.onBuyClick, this);
|
||||
this.buy_node.off(NodeEventType.TOUCH_CANCEL, this.onBuyTouchCancel, this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,10 +104,33 @@ export class EquipListComp extends CCComp {
|
||||
/**
|
||||
* 初始化装备卡数据并渲染 UI
|
||||
*
|
||||
* 若槽位已有旧卡且显示中,先播普通逝去动画(缩小淡出),结束后切新卡;
|
||||
* 刚购买的槽位跳过逝去动画直接应用新卡(购买动画已播放大淡出)。
|
||||
*
|
||||
* @param data 装备卡配置(必须为 trigger_type=Field 的装备卡)
|
||||
*/
|
||||
applyCardData(data: CardConfig): void {
|
||||
if (!data) return;
|
||||
|
||||
// 刚购买(已播放大逝去动画)→ 不播普通逝去动画,直接应用新卡
|
||||
if (this.isPurchased) {
|
||||
this.cardData = data;
|
||||
this.isPurchased = false;
|
||||
this.updateUI();
|
||||
return;
|
||||
}
|
||||
|
||||
// 旧卡存在且显示中 → 播普通逝去动画,结束后切新卡
|
||||
if (this.cardData && this.node.active) {
|
||||
this.playRefreshExitAnim(() => {
|
||||
this.cardData = data;
|
||||
this.isPurchased = false;
|
||||
this.updateUI();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 首次赋值 → 直接渲染
|
||||
this.cardData = data;
|
||||
this.isPurchased = false;
|
||||
this.updateUI();
|
||||
@@ -150,6 +184,107 @@ export class EquipListComp extends CCComp {
|
||||
costLabel.string = `${this.cardData.cost ?? 0}`;
|
||||
}
|
||||
}
|
||||
|
||||
// 播放入场动画(由小变大 + 淡入)
|
||||
this.playEnterAnim();
|
||||
}
|
||||
|
||||
// ======================== 动画 ========================
|
||||
|
||||
/** 播放入场动画:卡牌由小变大(scale 0→1)+ 淡入 */
|
||||
private playEnterAnim() {
|
||||
Tween.stopAllByTarget(this.node);
|
||||
if (this.opacityComp) {
|
||||
Tween.stopAllByTarget(this.opacityComp);
|
||||
}
|
||||
this.node.setScale(0, 0, 1);
|
||||
if (this.opacityComp) {
|
||||
this.opacityComp.opacity = 0;
|
||||
}
|
||||
tween(this.node)
|
||||
.to(this.enterDuration, { scale: new Vec3(1, 1, 1) }, { easing: 'backOut' })
|
||||
.start();
|
||||
if (this.opacityComp) {
|
||||
tween(this.opacityComp)
|
||||
.to(this.enterDuration, { opacity: 255 })
|
||||
.start();
|
||||
}
|
||||
}
|
||||
|
||||
/** 播放购买动画:卡牌放大(scale 1→1.1)+ 淡出 */
|
||||
private playPurchaseAnim() {
|
||||
Tween.stopAllByTarget(this.node);
|
||||
if (this.opacityComp) {
|
||||
Tween.stopAllByTarget(this.opacityComp);
|
||||
}
|
||||
tween(this.node)
|
||||
.to(this.exitDuration, { scale: new Vec3(1.1, 1.1, 1) }, { easing: 'quadIn' })
|
||||
.start();
|
||||
if (this.opacityComp) {
|
||||
tween(this.opacityComp)
|
||||
.to(this.exitDuration, { opacity: 0 })
|
||||
.start();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 播放普通刷新"逝去"动画:旧卡缩小(scale 1→0)+ 淡出,结束后回调切换新卡。
|
||||
* @param onComplete 动画结束回调,用于应用新卡数据
|
||||
*/
|
||||
private playRefreshExitAnim(onComplete: () => void) {
|
||||
Tween.stopAllByTarget(this.node);
|
||||
if (this.opacityComp) {
|
||||
Tween.stopAllByTarget(this.opacityComp);
|
||||
}
|
||||
tween(this.node)
|
||||
.to(this.exitDuration, { scale: new Vec3(0, 0, 1) }, { easing: 'quadIn' })
|
||||
.start();
|
||||
if (this.opacityComp) {
|
||||
tween(this.opacityComp)
|
||||
.to(this.exitDuration, { opacity: 0 })
|
||||
.call(onComplete)
|
||||
.start();
|
||||
} else {
|
||||
this.scheduleOnce(onComplete, this.exitDuration);
|
||||
}
|
||||
}
|
||||
|
||||
// ======================== 按钮动画 ========================
|
||||
|
||||
/** 按钮正常缩放 */
|
||||
private readonly btnNormalScale: number = 1;
|
||||
/** 按钮按下缩放 */
|
||||
private readonly btnPressScale: number = 0.92;
|
||||
/** 按钮点击回弹峰值缩放 */
|
||||
private readonly btnClickScale: number = 1.08;
|
||||
|
||||
/** 购买按钮按下:缩小反馈 */
|
||||
private onBuyTouchStart() {
|
||||
this.playBtnScaleTo(this.btnPressScale, 0.06);
|
||||
}
|
||||
|
||||
/** 购买按钮取消:恢复缩放 */
|
||||
private onBuyTouchCancel() {
|
||||
this.playBtnScaleTo(this.btnNormalScale, 0.08);
|
||||
}
|
||||
|
||||
/** 按钮缩放动画(通用) */
|
||||
private playBtnScaleTo(scale: number, duration: number) {
|
||||
if (!this.buy_node || !this.buy_node.isValid) return;
|
||||
Tween.stopAllByTarget(this.buy_node);
|
||||
tween(this.buy_node)
|
||||
.to(duration, { scale: new Vec3(scale, scale, 1) })
|
||||
.start();
|
||||
}
|
||||
|
||||
/** 按钮点击回弹动画:先弹到峰值再回到正常 */
|
||||
private playBtnClickAnim() {
|
||||
if (!this.buy_node || !this.buy_node.isValid) return;
|
||||
Tween.stopAllByTarget(this.buy_node);
|
||||
tween(this.buy_node)
|
||||
.to(0.05, { scale: new Vec3(this.btnClickScale, this.btnClickScale, 1) })
|
||||
.to(0.08, { scale: new Vec3(this.btnNormalScale, this.btnNormalScale, 1) })
|
||||
.start();
|
||||
}
|
||||
|
||||
/** 更新图标精灵 */
|
||||
@@ -178,6 +313,9 @@ export class EquipListComp extends CCComp {
|
||||
private onBuyClick() {
|
||||
if (!this.cardData || this.isPurchased) return;
|
||||
|
||||
// 播放按钮点击回弹动画
|
||||
this.playBtnClickAnim();
|
||||
|
||||
oops.audio.playEffect("music/button");
|
||||
|
||||
// 扣费
|
||||
@@ -201,6 +339,9 @@ export class EquipListComp extends CCComp {
|
||||
this.buy_node.active = false;
|
||||
}
|
||||
|
||||
// 播放购买动画(卡牌放大 + 淡出)
|
||||
this.playPurchaseAnim();
|
||||
|
||||
mLogger.log(this.debugMode, "EquipListComp", "equipment purchased", {
|
||||
uuid: this.cardData.uuid,
|
||||
cost
|
||||
|
||||
Reference in New Issue
Block a user