import { _decorator, Component, Node, Camera, Vec3, tween, Quat, easing, TweenEasing, EventTouch, input, Input } from 'cc'; const { ccclass, property } = _decorator; // 定义镜头配置接口 interface CameraShot { position: Vec3; // 相机位置 lookAt: Vec3; // 看向的位置 duration?: number; // 过渡时间 delay?: number; // 停留时间 easing?: TweenEasing; // 改为 TweenEasing 类型 } @ccclass('CameraManager') export class CameraManager extends Component { @property(Camera) camera: Camera = null; @property defaultTransitionTime: number = 2.0; // 默认过渡时间 @property defaultStayTime: number = 3.0; // 默认停留时间 @property(Node) public defaultCamera: Node = null; @property(Node) public deadCamera: Node = null; private isPlaying: boolean = false; private currentShotIndex: number = 0; private shots: CameraShot[] = []; private readonly MIN_DEAD_ROTATION = -230; private readonly MAX_DEAD_ROTATION = -180; private deadCameraRotation: number = -180; private lastTouchX: number = 0; private readonly DEAD_CAMERA_ROTATION_SPEED = 0.3; private isTouchingDeadCamera: boolean = false; // 预设一些常用的镜头 readonly SHOTS = { OVERVIEW: { position: new Vec3(0, 30, 30), lookAt: new Vec3(0, 0, 0), duration: 2, delay: 3 }, SIDE_VIEW: { position: new Vec3(20, 5, 0), lookAt: new Vec3(0, 2, 0), duration: 2, delay: 3 }, PLAYER_VIEW: { position: new Vec3(0, 2, 60), lookAt: new Vec3(0, 2, 0), duration: 2, delay: 3 }, DOLL_VIEW: { position: new Vec3(0, 2, -10), lookAt: new Vec3(0, 2, -5), duration: 2, delay: 3 } }; start() { if (!this.camera) { this.camera = this.getComponent(Camera); } // 确保死亡摄像机初始隐藏 if (this.deadCamera) { this.deadCamera.active = false; } // 确保默认摄像机初始显示 if (this.defaultCamera) { this.defaultCamera.active = true; } } // 添加一个镜头到序列 addShot(shot: CameraShot) { this.shots.push({ position: shot.position, lookAt: shot.lookAt, duration: shot.duration || this.defaultTransitionTime, delay: shot.delay || this.defaultStayTime, easing: shot.easing || 'quadOut' as TweenEasing // 使用类型断言 }); } // 清空镜头序列 clearShots() { this.shots = []; this.currentShotIndex = 0; } // 开始播放镜头序列 async playShotsSequence(loop: boolean = false) { if (this.isPlaying || this.shots.length === 0) return; this.isPlaying = true; this.currentShotIndex = 0; while (this.isPlaying) { await this.playShot(this.shots[this.currentShotIndex]); this.currentShotIndex++; if (this.currentShotIndex >= this.shots.length) { if (loop) { this.currentShotIndex = 0; } else { break; } } } this.isPlaying = false; } // 停止播放 stopSequence() { this.isPlaying = false; } // 立即切换到指定镜头 setCameraShot(shot: CameraShot) { this.camera.node.setPosition(shot.position); this.camera.node.lookAt(shot.lookAt); } // 播放单个镜头 private playShot(shot: CameraShot): Promise { return new Promise((resolve) => { // 计算目标四元数 const targetQuat = new Quat(); const targetPos = shot.position.clone(); const up = new Vec3(0, 1, 0); // 计算朝向 const forward = Vec3.subtract(new Vec3(), shot.lookAt, shot.position).normalize(); const right = Vec3.cross(new Vec3(), forward, up).normalize(); Vec3.cross(up, right, forward); Quat.fromAxes(targetQuat, right, up, forward.multiplyScalar(-1)); // 创建动画 tween(this.camera.node) .parallel( tween().to(shot.duration, { position: targetPos }, { easing: shot.easing }), tween().to(shot.duration, { rotation: targetQuat }, { easing: shot.easing }) ) .delay(shot.delay) .call(() => resolve()) .start(); }); } // 示例:创建开场镜头序列 createIntroSequence() { this.clearShots(); this.addShot(this.SHOTS.OVERVIEW); this.addShot(this.SHOTS.SIDE_VIEW); this.addShot(this.SHOTS.PLAYER_VIEW); this.playShotsSequence(false); } // 示例:创建游戏结束镜头序列 createEndingSequence() { this.clearShots(); this.addShot(this.SHOTS.DOLL_VIEW); this.addShot(this.SHOTS.OVERVIEW); this.playShotsSequence(false); } switchToDeadCamera(playerPos: Vec3) { if (!this.deadCamera || !this.defaultCamera) { console.error('Camera references not set in CameraManager'); return; } // 设置死亡摄像机的初始位置和朝向 this.deadCamera.setWorldPosition(new Vec3( playerPos.x, playerPos.y + 2, playerPos.z + 5 )); // 初始朝向 this.deadCameraRotation = -180; this.deadCamera.eulerAngles = new Vec3(-15, this.deadCameraRotation, 0); // 切换摄像机 this.defaultCamera.active = false; this.deadCamera.active = true; // 添加触摸事件监听 this.enableDeadCameraControl(); } private enableDeadCameraControl() { input.on(Input.EventType.TOUCH_START, this.onDeadCameraTouchStart, this); input.on(Input.EventType.TOUCH_MOVE, this.onDeadCameraTouchMove, this); input.on(Input.EventType.TOUCH_END, this.onDeadCameraTouchEnd, this); input.on(Input.EventType.TOUCH_CANCEL, this.onDeadCameraTouchEnd, this); } private onDeadCameraTouchStart(event: EventTouch) { this.isTouchingDeadCamera = true; this.lastTouchX = event.getLocationX(); } private onDeadCameraTouchMove(event: EventTouch) { if (!this.isTouchingDeadCamera || !this.deadCamera) return; const currentTouchX = event.getLocationX(); const deltaX = currentTouchX - this.lastTouchX; this.deadCameraRotation -= deltaX * this.DEAD_CAMERA_ROTATION_SPEED; this.deadCameraRotation = Math.max(this.MIN_DEAD_ROTATION, Math.min(this.MAX_DEAD_ROTATION, this.deadCameraRotation)); this.deadCamera.eulerAngles = new Vec3(-15, this.deadCameraRotation, 0); this.lastTouchX = currentTouchX; } private onDeadCameraTouchEnd() { this.isTouchingDeadCamera = false; } onDestroy() { input.off(Input.EventType.TOUCH_START, this.onDeadCameraTouchStart, this); input.off(Input.EventType.TOUCH_MOVE, this.onDeadCameraTouchMove, this); input.off(Input.EventType.TOUCH_END, this.onDeadCameraTouchEnd, this); input.off(Input.EventType.TOUCH_CANCEL, this.onDeadCameraTouchEnd, this); } }