PlayerCamera.ts 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. import { _decorator, Component, math, Node, randomRange, Vec3 } from 'cc';
  2. const { ccclass, property } = _decorator;
  3. @ccclass('PlayerCamera')
  4. export class PlayerCamera extends Component {
  5. /** 是否允许相机抖动 */
  6. private canShake: boolean = true;
  7. /** 抖动持续时间 */
  8. private duration: number = 0;
  9. /** 已过去的时间 */
  10. private elapsed: number = 0;
  11. /** 计时器 */
  12. private timer: number = 0;
  13. /** 相机原始位置 */
  14. private originalPos: Vec3 = new Vec3();
  15. /** 抖动幅度 */
  16. private shakeAmplitude: number = 1;
  17. // 新增Z轴震动参数
  18. private targetZ: number = 0;
  19. private startZ: number = 0;
  20. /**
  21. * 组件开始运行时调用,记录相机的原始位置
  22. */
  23. start() {
  24. this.originalPos = this.node.position.clone();
  25. }
  26. /**
  27. * 触发相机抖动(新增Z轴参数)
  28. * @param duration - 抖动持续时间
  29. * @param amplitude - XY轴抖动幅度
  30. * @param zAmplitude - Z轴后坐力幅度
  31. */
  32. public shake(duration: number, amplitude: number, zAmplitude: number = 0) {
  33. if(this.canShake)return;
  34. this.canShake = true;
  35. this.duration = duration;
  36. this.shakeAmplitude = amplitude;
  37. // 记录Z轴初始位置并计算目标位置
  38. this.startZ = this.node.position.z;
  39. this.targetZ = this.startZ + zAmplitude;
  40. this.elapsed = 0;
  41. }
  42. update(deltaTime: number) {
  43. if (!this.canShake) {
  44. this.node.position = this.originalPos;
  45. return;
  46. }
  47. this.elapsed += deltaTime;
  48. const progress = Math.min(this.elapsed / this.duration, 1);
  49. //线性插值计算Z轴位置
  50. const currentZ = math.lerp(this.startZ, this.targetZ, this.easeOutQuad(progress));
  51. //XY轴保持随机抖动
  52. const xOffset = randomRange(-this.shakeAmplitude, this.shakeAmplitude);
  53. const yOffset = randomRange(-this.shakeAmplitude, this.shakeAmplitude);
  54. this.node.setPosition(
  55. this.originalPos.x + xOffset,
  56. this.originalPos.y + yOffset,
  57. currentZ
  58. );
  59. if (progress >= 1) {
  60. this.canShake = false;
  61. //最终确保回到精确的原始位置
  62. this.node.setPosition(this.originalPos.x, this.originalPos.y, this.startZ);
  63. }
  64. }
  65. /** 二次缓动函数 */
  66. private easeOutQuad(t: number): number {
  67. return t * (2 - t);
  68. }
  69. }