diff --git a/assets/resources/gui/element/card.prefab b/assets/resources/gui/element/card.prefab index 9222226c..f4fe153c 100644 --- a/assets/resources/gui/element/card.prefab +++ b/assets/resources/gui/element/card.prefab @@ -5686,7 +5686,7 @@ "__id__": 314 } ], - "_active": true, + "_active": false, "_components": [ { "__id__": 320 diff --git a/assets/script/game/common/config/GameEvent.ts b/assets/script/game/common/config/GameEvent.ts index 601cc955..030aae79 100644 --- a/assets/script/game/common/config/GameEvent.ts +++ b/assets/script/game/common/config/GameEvent.ts @@ -20,6 +20,8 @@ export enum GameEvent { CastSkill = "CastSkill", CardsClose = "CardsClose", CardRefresh = "CardRefresh", + /** 单张卡牌被点击选中(payload 为被点击的 CardComp 实例,用于其他卡牌联动隐藏 call_btn) */ + CardSelected = "CardSelected", UseHeroCard = "UseHeroCard", UseSkillCard = "UseSkillCard", UseSpecialCard = "UseSpecialCard", diff --git a/assets/script/game/map/CardComp.ts b/assets/script/game/map/CardComp.ts index 5195956c..85d80f93 100644 --- a/assets/script/game/map/CardComp.ts +++ b/assets/script/game/map/CardComp.ts @@ -135,10 +135,8 @@ export class CardComp extends CCComp { * 防止快速切卡时旧回调错误覆盖新图标。 */ private iconVisualToken: number = 0; - /** 是否触发了长按 */ - private isLongPressed: boolean = false; - /** 长按触发时间(秒) */ - private readonly LONG_PRESS_DURATION: number = 0.5; + /** 视为"点击"的最大位移阈值(像素),小于该值视为点击而非拖拽 */ + private readonly tapMoveThreshold: number = 10; // ======================== 生命周期 ======================== @@ -154,7 +152,8 @@ export class CardComp extends CCComp { this.opacityComp.opacity = 255; this.updateLockUI(); this.applyEmptyUI(); - + // call_btn 默认隐藏,仅在点击本卡时显示 + this.hideCallBtn(); } /** 组件销毁时解绑所有事件,防止残留回调 */ @@ -448,6 +447,7 @@ export class CardComp extends CCComp { this.node.setScale(new Vec3(1, 1, 1)); this.updateLockUI(); this.applyEmptyUI(); + this.hideCallBtn(); this.node.active = false; } @@ -461,6 +461,10 @@ export class CardComp extends CCComp { this.node.on(NodeEventType.TOUCH_CANCEL, this.onCardTouchCancel, this); this.Lock?.on(NodeEventType.TOUCH_END, this.onToggleLock, this); this.unLock?.on(NodeEventType.TOUCH_END, this.onToggleLock, this); + // 召唤按钮点击 = 使用卡牌 + this.call_btn?.on(NodeEventType.TOUCH_END, this.onCallBtnClick, this); + // 监听跨卡联动:其他卡牌被点击时隐藏本卡 call_btn + oops.message.on(GameEvent.CardSelected, this.onOtherCardSelected, this); } /** 解绑触控,防止节点销毁后残留回调 */ @@ -477,19 +481,20 @@ export class CardComp extends CCComp { if (this.unLock && this.unLock.isValid) { this.unLock.off(NodeEventType.TOUCH_END, this.onToggleLock, this); } + if (this.call_btn && this.call_btn.isValid) { + this.call_btn.off(NodeEventType.TOUCH_END, this.onCallBtnClick, this); + } + oops.message.off(GameEvent.CardSelected, this.onOtherCardSelected, this); } // ======================== 触摸交互 ======================== - /** 触摸开始:记录起点 Y,进入拖拽状态 */ + /** 触摸开始:记录起点坐标,进入拖拽状态 */ private onCardTouchStart(event: EventTouch) { if (!this.cardData || this.isUsing) return; this.touchStartY = event.getUILocation().y; this.touchStartX = event.getUILocation().x; this.isDragging = true; - this.isLongPressed = false; - this.unschedule(this.onLongPress); - this.scheduleOnce(this.onLongPress, this.LONG_PRESS_DURATION); } /** @@ -499,25 +504,15 @@ 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); - if (deltaY > 10) { - this.unschedule(this.onLongPress); - if (this.isLongPressed) { - this.isLongPressed = false; - oops.gui.remove(UIID.HInfo); - } - } - this.node.setPosition(this.restPosition.x, this.restPosition.y + deltaY, this.restPosition.z); } /** * 触摸结束: - * - 技能卡:点击即可使用 - * - 英雄卡/其他:上拉距离 >= dragUseThreshold → 视为"使用卡牌" - * - 否则视为"点击"或者"长按结束" + * - 上拉距离 >= dragUseThreshold → 视为"使用卡牌" + * - 位移很小(点击)→ 触发 onCardTap:显示 call_btn / 打开信息面板 / 通知其他卡牌联动 */ private onCardTouchEnd(event: EventTouch) { - this.unschedule(this.onLongPress); if (!this.isDragging || !this.cardData || this.isUsing) return; const endY = event.getUILocation().y; const endX = event.getUILocation().x; @@ -525,11 +520,6 @@ export class CardComp extends CCComp { const deltaX = endX - this.touchStartX; this.isDragging = false; - if (this.isLongPressed) { - this.isLongPressed = false; - oops.gui.remove(UIID.HInfo); - } - // 英雄卡保持上划使用 if (deltaY >= this.dragUseThreshold) { const used = this.useCard(); @@ -539,31 +529,70 @@ export class CardComp extends CCComp { return; } + // 位移小于阈值视为"点击" + if (Math.abs(deltaY) < this.tapMoveThreshold && Math.abs(deltaX) < this.tapMoveThreshold) { + this.onCardTap(); + return; + } + this.playReboundAnim(); } /** 触摸取消:回弹至原位 */ private onCardTouchCancel() { - this.unschedule(this.onLongPress); if (!this.isDragging || this.isUsing) return; this.isDragging = false; - if (this.isLongPressed) { - this.isLongPressed = false; - oops.gui.remove(UIID.HInfo); - } this.playReboundAnim(); } - /** 长按触发:英雄卡打开英雄信息预览面板 */ - private onLongPress() { - if (!this.isDragging || this.isUsing) return; - if (!this.cardData || this.card_type !== CardType.Hero) return; - this.isLongPressed = true; - const heroUuid = this.card_uuid; - const heroLv = Math.max(1, this.cardData.hero_lv ?? 1); - const poolLv = Math.max(1, this.cardData.base_pool_lv ?? this.cardData.pool_lv ?? 1); - oops.gui.remove(UIID.HInfo); - oops.gui.open(UIID.HInfo, { heroUuid, heroLv, poolLv }); + /** + * 卡牌被点击(非拖拽): + * 1. 显示本卡的召唤按钮 call_btn。 + * 2. 派发 CardSelected 事件,其他卡牌收到后隐藏各自的 call_btn。 + * 3. 英雄卡打开 HInfo 信息面板(点击查看,替代原长按)。 + */ + private onCardTap() { + this.playReboundAnim(); + this.showCallBtn(); + oops.message.dispatchEvent(GameEvent.CardSelected, this); + // 英雄卡打开信息面板(点击替代长按) + if (this.card_type === CardType.Hero) { + const heroUuid = this.card_uuid; + const heroLv = Math.max(1, this.cardData?.hero_lv ?? 1); + const poolLv = Math.max(1, this.cardData?.base_pool_lv ?? this.cardData?.pool_lv ?? 1); + oops.gui.remove(UIID.HInfo); + oops.gui.open(UIID.HInfo, { heroUuid, heroLv, poolLv }); + } + } + + /** + * 其他卡牌被点击时联动隐藏本卡 call_btn。 + * @param event 事件名(ListenerFunc 约定的第一个参数) + * @param source 被点击的 CardComp 实例 + */ + private onOtherCardSelected(event: string, source: CardComp) { + if (source === this) return; + this.hideCallBtn(); + } + + /** 显示召唤按钮 */ + private showCallBtn() { + if (this.call_btn && this.call_btn.isValid) { + this.call_btn.active = true; + } + } + + /** 隐藏召唤按钮 */ + private hideCallBtn() { + if (this.call_btn && this.call_btn.isValid) { + this.call_btn.active = false; + } + } + + /** 召唤按钮点击回调:阻止冒泡后触发使用卡牌 */ + private onCallBtnClick(event: EventTouch) { + event.propagationStopped = true; + this.useCard(); } /**