squidGame/tgx-games-client/assets/module_arean/scripts/common/CameraOrbit.ts

118 lines
4.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// CameraOrbit.ts
import { _decorator, Component, Node, Vec3, EventTouch, input, Input, tween, Tween } from 'cc';
const { ccclass, property } = _decorator;
@ccclass('CameraOrbit')
export class CameraOrbit extends Component {
private lastTouchX: number = 0;
private readonly rotationSpeed: number = 0.6; // 旋转速度系数,可以根据需要调整
private autoRotateTween: Tween<Node> | null = null;
private isTouching: boolean = false;
private currentAngle: number = 0;
private centerPoint: Vec3 = new Vec3();
private radius: number = 0; // 移除 @property改为自动计算
private initialHeight: number = 0;
start() {
if (!this.node) return; // 添加节点检查
// 保存中心点Y轴位置设置为负值使摄像机向下倾斜
this.centerPoint.set(0, -5, 0);
this.initialHeight = this.node.position.y;
// 计算半径(根据初始位置到中心点的水平距离)
const initialPos = this.node.position;
this.radius = Math.sqrt(
initialPos.x * initialPos.x +
initialPos.z * initialPos.z
);
// 计算初始角度
this.currentAngle = Math.atan2(initialPos.x, initialPos.z) * 180 / Math.PI;
this.updateCameraPosition();
this.startAutoRotate();
}
private startAutoRotate() {
// 创建一个对象来存储和更新角度
const tweenTarget = { angle: this.currentAngle };
this.autoRotateTween = tween(tweenTarget)
.repeatForever(
tween()
.to(360, {
angle: 360
}, {
onUpdate: () => {
this.currentAngle = tweenTarget.angle;
this.updateCameraPosition();
}
})
)
.start();
}
private updateCameraPosition() {
if (!this.node) return; // 添加节点检查
const angleInRadians = this.currentAngle * Math.PI / 180;
const x = Math.sin(angleInRadians) * this.radius;
const z = Math.cos(angleInRadians) * this.radius;
this.node.setPosition(new Vec3(x, this.initialHeight, z));
this.node.lookAt(this.centerPoint);
// 移除180度偏移让摄像机朝向中心
this.node.setRotationFromEuler(0, this.currentAngle, 0);
}
onEnable() {
// 注册触摸事件
input.on(Input.EventType.TOUCH_START, this.onTouchStart, this);
input.on(Input.EventType.TOUCH_MOVE, this.onTouchMove, this);
input.on(Input.EventType.TOUCH_END, this.onTouchEnd, this);
input.on(Input.EventType.TOUCH_CANCEL, this.onTouchEnd, this);
}
onDisable() {
// 移除触摸事件监听
input.off(Input.EventType.TOUCH_START, this.onTouchStart, this);
input.off(Input.EventType.TOUCH_MOVE, this.onTouchMove, this);
input.off(Input.EventType.TOUCH_END, this.onTouchEnd, this);
input.off(Input.EventType.TOUCH_CANCEL, this.onTouchEnd, this);
}
private onTouchStart(event: EventTouch) {
this.isTouching = true;
this.lastTouchX = event.getLocationX();
// 暂停自动旋转
if (this.autoRotateTween) {
this.autoRotateTween.stop();
}
}
private onTouchMove(event: EventTouch) {
if (!this.isTouching) return;
// 计算触摸移动距离
const currentTouchX = event.getLocationX();
const deltaX = currentTouchX - this.lastTouchX;
// 更新角度
this.currentAngle -= deltaX * this.rotationSpeed;
// 确保角度在0-360范围内
this.currentAngle = (this.currentAngle + 360) % 360;
// 更新相机位置和朝向
this.updateCameraPosition();
// 更新上一次触摸位置
this.lastTouchX = currentTouchX;
}
private onTouchEnd() {
this.isTouching = false;
// 恢复自动旋转
this.startAutoRotate();
}
}