/** * @file ScreenShake.ts * @description 屏幕震动静态工具(表现层) * * 项目内无现成相机震动能力(MapViewScene.camera 可能为 null 且从未使用), * 改为抖动地图根节点 smc.map.MapView.node(地图+实体一起震,UI 层不受影响)。 * * 用法: * ScreenShake.shake(10, 0.4); // 强度 10 像素,持续 0.4 秒 */ import { tween, Tween, v3, Vec3 } from "cc"; import { smc } from "./SingletonModuleComp"; export class ScreenShake { /** 地图根节点的基准位置(首次震动时快照,用于收敛回原位,防多次震动漂移) */ private static basePos: Vec3 | null = null; /** * 触发一次屏幕震动 * @param strength 像素振幅(建议 4~10) * @param duration 总时长(秒,建议 0.2~0.4) */ static shake(strength: number = 8, duration: number = 0.3) { const target = smc.map?.MapView?.node; if (!target || !target.isValid) return; if (!this.basePos) this.basePos = target.position.clone(); // 打断进行中的震动(新震动覆盖旧震动,不做强度叠加,避免失控) Tween.stopAllByTarget(target); const steps = Math.max(1, Math.floor(duration / 0.04)); const t = tween(target); for (let i = 0; i < steps; i++) { t.to(0.04, { position: v3( this.basePos.x + (Math.random() * 2 - 1) * strength, this.basePos.y + (Math.random() * 2 - 1) * strength, this.basePos.z), }); } // 收敛回原位 t.to(0.05, { position: this.basePos }).start(); } }