squidGame/tgx-games-client/assets/module_arean/level1/Script/CameraManager.ts

241 lines
7.5 KiB
TypeScript

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<void> {
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);
}
}