import { _decorator, Component, math, Node, randomRange, Vec3 } from 'cc'; const { ccclass, property } = _decorator; @ccclass('PlayerCamera') export class PlayerCamera extends Component { /** 是否允许相机抖动 */ private canShake: boolean = true; /** 抖动持续时间 */ private duration: number = 0; /** 已过去的时间 */ private elapsed: number = 0; /** 计时器 */ private timer: number = 0; /** 相机原始位置 */ private originalPos: Vec3 = new Vec3(); /** 抖动幅度 */ private shakeAmplitude: number = 1; // 新增Z轴震动参数 private targetZ: number = 0; private startZ: number = 0; /** * 组件开始运行时调用,记录相机的原始位置 */ start() { this.originalPos = this.node.position.clone(); } /** * 触发相机抖动(新增Z轴参数) * @param duration - 抖动持续时间 * @param amplitude - XY轴抖动幅度 * @param zAmplitude - Z轴后坐力幅度 */ public shake(duration: number, amplitude: number, zAmplitude: number = 0) { if(this.canShake)return; this.canShake = true; this.duration = duration; this.shakeAmplitude = amplitude; // 记录Z轴初始位置并计算目标位置 this.startZ = this.node.position.z; this.targetZ = this.startZ + zAmplitude; this.elapsed = 0; } update(deltaTime: number) { if (!this.canShake) { this.node.position = this.originalPos; return; } this.elapsed += deltaTime; const progress = Math.min(this.elapsed / this.duration, 1); //线性插值计算Z轴位置 const currentZ = math.lerp(this.startZ, this.targetZ, this.easeOutQuad(progress)); //XY轴保持随机抖动 const xOffset = randomRange(-this.shakeAmplitude, this.shakeAmplitude); const yOffset = randomRange(-this.shakeAmplitude, this.shakeAmplitude); this.node.setPosition( this.originalPos.x + xOffset, this.originalPos.y + yOffset, currentZ ); if (progress >= 1) { this.canShake = false; //最终确保回到精确的原始位置 this.node.setPosition(this.originalPos.x, this.originalPos.y, this.startZ); } } /** 二次缓动函数 */ private easeOutQuad(t: number): number { return t * (2 - t); } }