2025-02-10 11:08:10 +08:00
|
|
|
|
// CameraOrbit.ts
|
2025-02-21 10:45:46 +08:00
|
|
|
|
import { _decorator, Component, Node, Vec3, EventTouch, input, Input, tween, Tween } from 'cc';
|
2025-02-10 11:08:10 +08:00
|
|
|
|
const { ccclass, property } = _decorator;
|
|
|
|
|
|
|
|
|
|
@ccclass('CameraOrbit')
|
|
|
|
|
export class CameraOrbit extends Component {
|
2025-02-21 10:45:46 +08:00
|
|
|
|
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;
|
|
|
|
|
|
2025-02-10 11:08:10 +08:00
|
|
|
|
start() {
|
2025-02-21 10:45:46 +08:00
|
|
|
|
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)
|
2025-02-10 11:08:10 +08:00
|
|
|
|
.repeatForever(
|
|
|
|
|
tween()
|
2025-02-21 10:45:46 +08:00
|
|
|
|
.to(360, {
|
|
|
|
|
angle: 360
|
|
|
|
|
}, {
|
|
|
|
|
onUpdate: () => {
|
|
|
|
|
this.currentAngle = tweenTarget.angle;
|
|
|
|
|
this.updateCameraPosition();
|
|
|
|
|
}
|
|
|
|
|
})
|
2025-02-10 11:08:10 +08:00
|
|
|
|
)
|
|
|
|
|
.start();
|
|
|
|
|
}
|
2025-02-21 10:45:46 +08:00
|
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
}
|
2025-02-10 11:08:10 +08:00
|
|
|
|
}
|