From cb2bc37a68e85eb021129eab17cdef30fc161763 Mon Sep 17 00:00:00 2001 From: panFD Date: Sun, 26 Jul 2026 20:13:41 +0800 Subject: [PATCH] =?UTF-8?q?refactor(map):=20=E4=BC=98=E5=8C=96=E6=8A=80?= =?UTF-8?q?=E8=83=BD=E7=9B=92=E4=B8=8E=E8=A3=85=E5=A4=87=E7=9B=92=E7=9A=84?= =?UTF-8?q?=E9=95=BF=E6=8C=89=E4=BA=A4=E4=BA=92=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将原有的单点触摸触发改为长按触发,统一使用触摸开始/结束/取消事件实现长按检测,添加长按计时和状态标记,修复短按误触发的问题,同时在组件销毁时清理计时器防止内存泄漏。 --- assets/script/game/map/EquipBoxComp.ts | 39 +++++++++++++++++++++++--- assets/script/game/map/SkillBoxComp.ts | 39 +++++++++++++++++++++++--- 2 files changed, 70 insertions(+), 8 deletions(-) diff --git a/assets/script/game/map/EquipBoxComp.ts b/assets/script/game/map/EquipBoxComp.ts index 93fb670b..9ca24072 100644 --- a/assets/script/game/map/EquipBoxComp.ts +++ b/assets/script/game/map/EquipBoxComp.ts @@ -123,7 +123,10 @@ export class EquipBoxComp extends CCComp { oops.message.on(GameEvent.MissionEnd, this.onMissionEnd, this); this.node.on(GameEvent.NewWave, this.onNewWave, this); oops.message.on(GameEvent.NewWave, this.onNewWaveGlobal, this); - this.node.on(NodeEventType.TOUCH_END, this.onNodeClicked, this); + // 长按弹出信息框:按下启动计时,放开/取消时关闭 + this.node.on(NodeEventType.TOUCH_START, this.onTouchStart, this); + this.node.on(NodeEventType.TOUCH_END, this.onTouchEnd, this); + this.node.on(NodeEventType.TOUCH_CANCEL, this.onTouchEnd, this); } /** 销毁时移除所有事件监听并通知槽位管理器回收 */ @@ -140,17 +143,45 @@ export class EquipBoxComp extends CCComp { oops.message.off(GameEvent.ReviveSuccess, this.onEventTrigger, this); if (this.node && this.node.isValid) { this.node.off(GameEvent.NewWave, this.onNewWave, this); - this.node.off(NodeEventType.TOUCH_END, this.onNodeClicked, this); + this.node.off(NodeEventType.TOUCH_START, this.onTouchStart, this); + this.node.off(NodeEventType.TOUCH_END, this.onTouchEnd, this); + this.node.off(NodeEventType.TOUCH_CANCEL, this.onTouchEnd, this); } + // 清理长按计时器,防止销毁后回调访问失效节点 + this.unschedule(this.showInfo); oops.message.off(GameEvent.NewWave, this.onNewWaveGlobal, this); // 通知 MissEquipComp 回收该节点占用的槽位 oops.message.dispatchEvent(GameEvent.RemoveEquipBox, this.node); } - private onNodeClicked() { + /** 长按时长(秒) */ + private static readonly LONG_PRESS_TIME: number = 0.5; + /** 信息框是否已弹出(区分长按完成与短按取消) */ + private info_shown: boolean = false; + + /** 按下:启动长按计时 */ + private onTouchStart() { if (!this.initialized) return; + this.info_shown = false; + this.scheduleOnce(this.showInfo, EquipBoxComp.LONG_PRESS_TIME); + } + + /** 放开/取消:已弹出则关闭信息框,未弹出则取消长按计时 */ + private onTouchEnd() { + this.unschedule(this.showInfo); + if (this.info_shown) { + this.info_shown = false; + // oops.gui 移除信息框 + oops.gui.remove(UIID.HInfo); + } + } + + /** 长按到点:弹出信息框 */ + private showInfo() { + if (!this.initialized) return; + this.info_shown = true; oops.audio.playEffect("music/button"); - // 点击装备盒弹出 HInfoComp,从 EquipPoolList 查询配置 + // 弹出 HInfoComp,从 EquipPoolList 查询配置 oops.gui.remove(UIID.HInfo); oops.gui.open(UIID.HInfo, { heroUuid: this.s_uuid, heroLv: this.card_lv, poolLv: 1, isSkillCard: true, isEquipCard: true }); } diff --git a/assets/script/game/map/SkillBoxComp.ts b/assets/script/game/map/SkillBoxComp.ts index 7815d8b6..c767df99 100644 --- a/assets/script/game/map/SkillBoxComp.ts +++ b/assets/script/game/map/SkillBoxComp.ts @@ -122,7 +122,10 @@ export class SkillBoxComp extends CCComp { oops.message.on(GameEvent.MissionEnd, this.onMissionEnd, this); this.node.on(GameEvent.NewWave, this.onNewWave, this); oops.message.on(GameEvent.NewWave, this.onNewWaveGlobal, this); - this.node.on(NodeEventType.TOUCH_END, this.onNodeClicked, this); + // 长按弹出信息框:按下启动计时,放开/取消时关闭 + this.node.on(NodeEventType.TOUCH_START, this.onTouchStart, this); + this.node.on(NodeEventType.TOUCH_END, this.onTouchEnd, this); + this.node.on(NodeEventType.TOUCH_CANCEL, this.onTouchEnd, this); } /** 销毁时移除所有事件监听并通知槽位管理器回收 */ @@ -139,17 +142,45 @@ export class SkillBoxComp extends CCComp { oops.message.off(GameEvent.ReviveSuccess, this.onEventTrigger, this); if (this.node && this.node.isValid) { this.node.off(GameEvent.NewWave, this.onNewWave, this); - this.node.off(NodeEventType.TOUCH_END, this.onNodeClicked, this); + this.node.off(NodeEventType.TOUCH_START, this.onTouchStart, this); + this.node.off(NodeEventType.TOUCH_END, this.onTouchEnd, this); + this.node.off(NodeEventType.TOUCH_CANCEL, this.onTouchEnd, this); } + // 清理长按计时器,防止销毁后回调访问失效节点 + this.unschedule(this.showInfo); oops.message.off(GameEvent.NewWave, this.onNewWaveGlobal, this); // 通知 MissSkillsComp 回收该节点占用的槽位 oops.message.dispatchEvent(GameEvent.RemoveSkillBox, this.node); } - private onNodeClicked() { + /** 长按时长(秒) */ + private static readonly LONG_PRESS_TIME: number = 0.5; + /** 信息框是否已弹出(区分长按完成与短按取消) */ + private info_shown: boolean = false; + + /** 按下:启动长按计时 */ + private onTouchStart() { if (!this.initialized) return; + this.info_shown = false; + this.scheduleOnce(this.showInfo, SkillBoxComp.LONG_PRESS_TIME); + } + + /** 放开/取消:已弹出则关闭信息框,未弹出则取消长按计时 */ + private onTouchEnd() { + this.unschedule(this.showInfo); + if (this.info_shown) { + this.info_shown = false; + // oops.gui 移除信息框 + oops.gui.remove(UIID.HInfo); + } + } + + /** 长按到点:弹出信息框 */ + private showInfo() { + if (!this.initialized) return; + this.info_shown = true; oops.audio.playEffect("music/button"); - // 点击时弹出 HInfoComp,传入卡牌 UUID 和等级以启用预览模式 + // 弹出 HInfoComp,传入卡牌 UUID 和等级以启用预览模式 const config = SkillCardList.find(c => c.uuid === this.s_uuid || c.skill === this.s_uuid); const cardUuid = config ? config.uuid : this.s_uuid;