|
@@ -42,8 +42,7 @@ export class LevelAction extends Component {
|
|
|
|
|
|
//镜头拉近属性
|
|
|
private _zoomDuration: number = 0.5; // 拉近持续时间(秒)
|
|
|
-
|
|
|
- private _raycastType: ERaycastType = ERaycastType.ALL;
|
|
|
+ private isTweening: boolean = false;
|
|
|
|
|
|
onLoad(): void {
|
|
|
this._cameraOriginalPos = this.camera.node.position.clone();
|
|
@@ -165,73 +164,48 @@ export class LevelAction extends Component {
|
|
|
const camera = this.camera;
|
|
|
if (!targetNode || !camera) return;
|
|
|
|
|
|
- const targetWorldPos = targetNode.worldPosition.clone();
|
|
|
- const screenPos = camera.worldToScreen(targetWorldPos, new Vec3());
|
|
|
-
|
|
|
- const screenSize = view.getVisibleSize();
|
|
|
- const isInView = screenPos.z > 0 &&
|
|
|
- screenPos.x >= 0 && screenPos.x <= screenSize.x &&
|
|
|
- screenPos.y >= 0 && screenPos.y <= screenSize.y;
|
|
|
-
|
|
|
- if (isInView) {
|
|
|
- this.preciselyLookAt(targetNode);
|
|
|
- } else {
|
|
|
- // this.coarselyTurnToTarget(targetNode);
|
|
|
- }
|
|
|
- await this.saveCameraState();
|
|
|
- }
|
|
|
+ const targetPos = new Vec3();
|
|
|
+ targetNode.getWorldPosition(targetPos);
|
|
|
+
|
|
|
+ // 获取相机位置
|
|
|
+ const cameraPos = new Vec3();
|
|
|
+ camera.node.getWorldPosition(cameraPos);
|
|
|
+
|
|
|
+ // 计算从相机到目标的方向向量
|
|
|
+ const direction = new Vec3();
|
|
|
+ Vec3.subtract(direction, targetPos, cameraPos);
|
|
|
+ direction.normalize();
|
|
|
+
|
|
|
+ // 计算目标欧拉角
|
|
|
+ const targetYaw = math.toDegree(Math.atan2(-direction.x, -direction.z));
|
|
|
+ const targetPitch = math.toDegree(Math.asin(direction.y));
|
|
|
+
|
|
|
+ // 获取当前欧拉角
|
|
|
+ const currentRotation = camera.node.eulerAngles.clone();
|
|
|
+
|
|
|
+ // 创建一个对象用于tween
|
|
|
+ const tweenObj = {
|
|
|
+ pitch: currentRotation.x,
|
|
|
+ yaw: currentRotation.y
|
|
|
+ };
|
|
|
+
|
|
|
+ this.isTweening = true;
|
|
|
+ tween(tweenObj)
|
|
|
+ .to(0.5, {
|
|
|
+ pitch: targetPitch,
|
|
|
+ yaw: targetYaw
|
|
|
+ }, {
|
|
|
+ easing: 'smooth',
|
|
|
+ onUpdate: () => {
|
|
|
+ // 更新相机旋转
|
|
|
+ camera.node.setRotationFromEuler(tweenObj.pitch, tweenObj.yaw, 0);
|
|
|
+ },
|
|
|
+ onComplete: () => {
|
|
|
+ this.isTweening = false;
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .start();
|
|
|
|
|
|
- //粗略旋转,控制相机大致朝向目标
|
|
|
- private coarselyTurnToTarget(targetNode: Node) {
|
|
|
- const camera = this.camera.node;
|
|
|
- const targetPos = targetNode.worldPosition.clone();
|
|
|
-
|
|
|
- // 计算目标方向向量
|
|
|
- const direction = new Vec3();
|
|
|
- Vec3.subtract(direction, targetPos, camera.worldPosition);
|
|
|
- direction.normalize();
|
|
|
-
|
|
|
- // 计算粗略旋转角度
|
|
|
- const roughRotation = new Vec3();
|
|
|
- roughRotation.y = Math.atan2(direction.x, direction.z) * 180 / Math.PI;
|
|
|
- roughRotation.x = -Math.asin(direction.y) * 180 / Math.PI;
|
|
|
- roughRotation.z = 0; // 保持Z轴不变
|
|
|
-
|
|
|
- // 使用缓动动画旋转相机
|
|
|
- tween(camera.eulerAngles)
|
|
|
- .to(0.3, roughRotation, {
|
|
|
- easing: 'sineOut',
|
|
|
- onUpdate: (target: Vec3) => {
|
|
|
- camera.setRotationFromEuler(target);
|
|
|
- }
|
|
|
- })
|
|
|
- .start();
|
|
|
- }
|
|
|
-
|
|
|
- //精准对准
|
|
|
- private preciselyLookAt(targetNode: Node) {
|
|
|
- const camera = this.camera.node;
|
|
|
- const targetPos = targetNode.worldPosition.clone();
|
|
|
-
|
|
|
- // 保存初始旋转状态
|
|
|
- const initialRotation = this._originalRotation.clone();
|
|
|
-
|
|
|
- // 计算目标相对于相机的方向
|
|
|
- const direction = new Vec3();
|
|
|
- Vec3.subtract(direction, targetPos, camera.worldPosition);
|
|
|
- direction.normalize();
|
|
|
-
|
|
|
- // 基于初始旋转状态计算新角度
|
|
|
- const newRotation = new Vec3();
|
|
|
- newRotation.y = initialRotation.y - direction.x * 10; // 调整系数
|
|
|
- newRotation.x = initialRotation.x + direction.y * 10;
|
|
|
-
|
|
|
- // 应用旋转限制
|
|
|
- newRotation.x = Math.max(this.minXRotation, Math.min(this.maxXRotation, newRotation.x));
|
|
|
- newRotation.y = Math.max(this.minYRotation, Math.min(this.maxYRotation, newRotation.y));
|
|
|
-
|
|
|
- // 设置相机旋转
|
|
|
- camera.setRotationFromEuler(newRotation);
|
|
|
}
|
|
|
|
|
|
private adjustRotationLimits() {
|