diff --git a/assets/script/game/map/MissionCardComp.ts b/assets/script/game/map/MissionCardComp.ts index 90830236..f21a545c 100644 --- a/assets/script/game/map/MissionCardComp.ts +++ b/assets/script/game/map/MissionCardComp.ts @@ -226,8 +226,8 @@ export class MissionCardComp extends CCComp { // ======================== 新手按钮指引 ======================== - /** 新手按钮指引抖动最大角度(度) */ - private static readonly BUTTON_GUIDE_SHAKE_ANGLE: number = 10; + /** 新手按钮指引脉动放大倍率 */ + private static readonly BUTTON_GUIDE_PULSE_SCALE: number = 1.15; /** 新手按钮指引每步时长(秒) */ private static readonly BUTTON_GUIDE_STEP_DURATION: number = 4.2; /** 新手按钮指引气泡停留时长(秒) */ @@ -743,7 +743,7 @@ export class MissionCardComp extends CCComp { this.updatePanelButtonsInteractable(); } - + // 英雄登场后同步英雄信息盒 this.refreshHeroBoxSlots(); @@ -929,7 +929,7 @@ export class MissionCardComp extends CCComp { /** * 启动新手按钮指引:依次指引 英雄→装备→技能→药品 四个面板按钮。 - * 每步播放 bg/icon 循环抖动 + smalltip 气泡文案, + * 每步播放 bg/icon 循环缩放脉动 + smalltip 气泡文案, * 已完成的步骤(smc.data.tip_done 对应键为 true)自动跳过,仅提醒 1 次。 */ private playButtonGuide() { @@ -960,11 +960,11 @@ export class MissionCardComp extends CCComp { if (!step) return; const btn = step.getBtn(); if (btn && btn.isValid) { - this.playGuideShake(btn, true); + this.playGuidePulse(btn, true); this.showGuideTip(btn, step.text); } this.scheduleOnce(() => { - this.stopGuideShake(btn); + this.stopGuidePulse(btn); // 本步提醒完成:记录完成标记(即使中止也只标记已播完的步骤) smc.data.tip_done[step.key] = true; this.nextButtonGuideStep(); @@ -980,12 +980,12 @@ export class MissionCardComp extends CCComp { /** * 中止指引(任务结束 / 组件销毁时调用): - * 停止所有抖动动画、还原气泡文案并隐藏气泡。 + * 停止所有缩放脉动动画、还原气泡文案并隐藏气泡。 */ private stopButtonGuide() { if (this.guideStepIndex < 0 && this.guideTipTextCache.size === 0) return; for (const step of this.guideSteps) { - this.stopGuideShake(step.getBtn()); + this.stopGuidePulse(step.getBtn()); } this.restoreGuideTipTexts(); this.guideStepIndex = -1; @@ -1005,39 +1005,38 @@ export class MissionCardComp extends CCComp { } /** - * 对按钮 bg/icon 子节点播放循环抖动动画。 - * 使用 angle 往复 tween,不修改 position,避免与 Widget 布局冲突。 + * 对按钮 bg/icon 子节点播放循环缩放脉动动画。 + * 使用 scale 往复 tween,不修改 position,避免与 Widget 布局冲突。 * @param btn 面板按钮节点(内部含 bg/icon 子节点) - * @param repeat 是否无限循环(true = 循环抖动) + * @param repeat 是否无限循环(true = 循环脉动) */ - private playGuideShake(btn: Node, repeat: boolean) { - const angle = MissionCardComp.BUTTON_GUIDE_SHAKE_ANGLE; + private playGuidePulse(btn: Node, repeat: boolean) { + const pulseScale = MissionCardComp.BUTTON_GUIDE_PULSE_SCALE; for (const name of ["bg", "icon"]) { const child = btn.getChildByName(name); if (!child || !child.isValid) continue; Tween.stopAllByTarget(child); - child.angle = 0; - // 单轮抖动约 0.94s(含间歇),节奏放慢避免高频晃动过刺眼 - let t = tween(child) - .to(0.15, { angle: angle }) - .to(0.3, { angle: -angle }) - .to(0.15, { angle: 0 }) - .delay(0.34); + child.setScale(1, 1, 1); + // 单轮脉动约 0.6s,持续闪动与气泡停留节奏一致 + const pulseTween = tween(child) + .to(0.3, { scale: new Vec3(pulseScale, pulseScale, 1) }, { easing: 'sineInOut' }) + .to(0.3, { scale: new Vec3(1, 1, 1) }, { easing: 'sineInOut' }); if (repeat) { - t = t.repeatForever(); + tween(child).repeatForever(pulseTween).start(); + } else { + pulseTween.start(); } - t.start(); } } - /** 停止按钮 bg/icon 抖动并复位角度 */ - private stopGuideShake(btn: Node | null) { + /** 停止按钮 bg/icon 缩放脉动并复位缩放 */ + private stopGuidePulse(btn: Node | null) { if (!btn || !btn.isValid) return; for (const name of ["bg", "icon"]) { const child = btn.getChildByName(name); if (!child || !child.isValid) continue; Tween.stopAllByTarget(child); - child.angle = 0; + child.setScale(1, 1, 1); } } diff --git a/assets/script/game/map/MissionHomeComp.ts b/assets/script/game/map/MissionHomeComp.ts index 753b7dc9..ff516d46 100644 --- a/assets/script/game/map/MissionHomeComp.ts +++ b/assets/script/game/map/MissionHomeComp.ts @@ -39,34 +39,34 @@ const { ccclass, property } = _decorator; export class MissionHomeComp extends CCComp { /** 调试日志开关 */ debugMode: boolean = false; -/** 开始游戏按钮节点(预留) */ + /** 开始游戏按钮节点(预留) */ @property(Node) - start_btn=null! + start_btn = null! /** 主页按钮节点(预留) */ @property(Node) - home_btn=null! + home_btn = null! /** 英雄图鉴按钮节点(预留) */ @property(Node) - hero_btn=null! + hero_btn = null! /** 排行榜按钮节点 */ @property(Node) - rank_btn=null! + rank_btn = null! /** 天赋按钮节点 */ @property(Node) - tals_btn=null! + tals_btn = null! - - @property(Node) - heros_page=null! - @property(Node) - talents_page=null! - @property(Node) - ranks_page=null! - // ======================== 新手指引(开始按钮抖动 + 气泡) ======================== + @property(Node) + heros_page = null! + @property(Node) + talents_page = null! + @property(Node) + ranks_page = null! - /** 抖动最大角度(度) */ - private static readonly SHAKE_ANGLE: number = 10; + // ======================== 新手指引(开始按钮缩放脉动 + 气泡) ======================== + + /** 脉动放大倍率 */ + private static readonly PULSE_SCALE: number = 1.15; /** 气泡文案 */ private static readonly TIP_TEXT: string = "点击开始游戏"; /** 气泡弹出/停留/收起节奏(秒) */ @@ -77,29 +77,29 @@ export class MissionHomeComp extends CCComp { /** 气泡原文缓存(指引结束后还原) */ private guideTipOriginText: string = ""; - + /** 注册任务结束事件 */ protected onLoad(): void { - this.on(GameEvent.MissionEnd,this.mission_end,this) + this.on(GameEvent.MissionEnd, this.mission_end, this) } /** 启动时显示主页 */ start() { this.home_active() - // 新玩家:start_btn 抖动 + smalltip 气泡引导点击开始(仅 1 次) + // 新玩家:start_btn 缩放脉动 + smalltip 气泡引导点击开始(仅 1 次) if (!smc.data.tip_done.start) { this.playStartGuide(); } } - onEnable(){ + onEnable() { } - update(dt:number){ - + update(dt: number) { + } - + /** * 开始任务: * 1. 打印日志。 @@ -110,12 +110,12 @@ export class MissionHomeComp extends CCComp { start_mission() { mLogger.log(this.debugMode, 'MissionHomeComp', "start_mission") - // 点击开始后完成指引:停止抖动/气泡并记录完成标记 + // 点击开始后完成指引:停止缩放脉动/气泡并记录完成标记 this.stopStartGuide(); smc.data.tip_done.start = true; oops.gui.open(UIID.Mission) - this.node.active=false; + this.node.active = false; // 隐藏 mapLayer 下的 main 节点 @@ -124,24 +124,24 @@ export class MissionHomeComp extends CCComp { // ======================== 新手指引实现 ======================== - /** 启动指引:button 子节点循环抖动 + smalltip 气泡弹出 */ + /** 启动指引:button 子节点循环缩放脉动 + smalltip 气泡弹出 */ private playStartGuide() { const btn = this.start_btn; if (!btn || !btn.isValid) return; if (this.guiding) return; this.guiding = true; - // start_btn 下名为 "Button" 的子节点循环抖动(angle 往复,不触碰 position,避免与布局冲突) - const shakeNode = this.getShakeNode(); - if (shakeNode) { - Tween.stopAllByTarget(shakeNode); - shakeNode.angle = 0; - tween(shakeNode) - .to(0.15, { angle: MissionHomeComp.SHAKE_ANGLE }) - .to(0.3, { angle: -MissionHomeComp.SHAKE_ANGLE }) - .to(0.15, { angle: 0 }) - .delay(0.34) - .repeatForever() + // start_btn 下名为 "Button" 的子节点循环缩放脉动(scale 往复,不触碰 position,避免与布局冲突) + const pulseNode = this.getPulseNode(); + if (pulseNode) { + Tween.stopAllByTarget(pulseNode); + pulseNode.setScale(1, 1, 1); + tween(pulseNode) + .repeatForever( + tween(pulseNode) + .to(0.3, { scale: new Vec3(MissionHomeComp.PULSE_SCALE, MissionHomeComp.PULSE_SCALE, 1) }, { easing: 'sineInOut' }) + .to(0.3, { scale: new Vec3(1, 1, 1) }, { easing: 'sineInOut' }) + ) .start(); } @@ -163,17 +163,17 @@ export class MissionHomeComp extends CCComp { } } - /** 停止指引:抖动复位、气泡收起并还原原文 */ + /** 停止指引:脉动复位、气泡收起并还原原文 */ private stopStartGuide() { if (!this.guiding) return; this.guiding = false; const btn = this.start_btn; if (btn && btn.isValid) { - const shakeNode = this.getShakeNode(); - if (shakeNode && shakeNode.isValid) { - Tween.stopAllByTarget(shakeNode); - shakeNode.angle = 0; + const pulseNode = this.getPulseNode(); + if (pulseNode && pulseNode.isValid) { + Tween.stopAllByTarget(pulseNode); + pulseNode.setScale(1, 1, 1); } const tip = btn.getChildByName("smalltip"); if (tip && tip.isValid) { @@ -186,10 +186,10 @@ export class MissionHomeComp extends CCComp { } /** - * 获取 start_btn 下名为 "Button" 的子节点(即要抖动的节点)。 + * 获取 start_btn 下名为 "Button" 的子节点(即要播放缩放脉动的节点)。 * @returns Button 子节点;未找到返回 null */ - private getShakeNode(): Node | null { + private getPulseNode(): Node | null { const btn = this.start_btn; if (!btn || !btn.isValid) return null; const node = btn.getChildByName("Button"); @@ -234,25 +234,25 @@ export class MissionHomeComp extends CCComp { this.showPage(this.talents_page) } /** 任务结束回调:重新显示主页 */ - mission_end(){ + mission_end() { mLogger.log(this.debugMode, 'MissionHomeComp', "[MissionHomeComp]=>mission_end") this.home_active() } /** 激活主页显示:刷新数据并显示节点 */ - home_active(){ + home_active() { // 任务结束回到主页:确保指引动画与气泡无残留 this.stopStartGuide(); this.uodate_data() this.hideAllPages() - this.node.active=true + this.node.active = true // 播放主页背景音乐,恢复默认音量 oops.audio.volumeMusic = 1.0; oops.audio.playerMusicLoop("music/home") } /** 更新主页显示数据(预留) */ - uodate_data(){ + uodate_data() { } @@ -260,10 +260,10 @@ export class MissionHomeComp extends CCComp { * 判断是否运行在微信小游戏环境。 * @returns true = 微信小游戏环境 */ - isWxClient(){ + isWxClient() { return typeof wx !== 'undefined' && typeof (wx as any).getSystemInfoSync === 'function'; } - + /** ECS 组件移除时销毁节点 */ reset() {