|
|
@@ -1,4 +1,4 @@
|
|
|
-import { _decorator, Component, Node, Vec3, tween, Tween } from 'cc';
|
|
|
+import { _decorator, Component, Node, Vec3, tween, Tween, UITransform, Camera } from 'cc';
|
|
|
const { ccclass, property } = _decorator;
|
|
|
|
|
|
/**
|
|
|
@@ -24,9 +24,12 @@ export class GameStartMove extends Component {
|
|
|
})
|
|
|
public cameraNode: Node = null;
|
|
|
|
|
|
- /** Offset (in pixels/units) for one step of movement. */
|
|
|
- @property({ tooltip: 'Vertical offset for the camera movement.' })
|
|
|
- public offset: number = 182;
|
|
|
+ /** Reference line node for camera positioning. When set, camera will move to show this line at the bottom. */
|
|
|
+ @property({
|
|
|
+ type: Node,
|
|
|
+ tooltip: 'Reference line node. Camera will move to position this line at the bottom of the view.'
|
|
|
+ })
|
|
|
+ public referenceLineNode: Node = null;
|
|
|
|
|
|
/** Tween duration for the smooth move-up animation. */
|
|
|
@property({ tooltip: 'Duration for the smooth move-up tween (seconds).' })
|
|
|
@@ -42,6 +45,8 @@ export class GameStartMove extends Component {
|
|
|
@property({ type: Node, tooltip: 'Canvas/GameLevelUI/Gray节点' })
|
|
|
public grayNode: Node = null;
|
|
|
|
|
|
+
|
|
|
+
|
|
|
private _originalDibanPos: Vec3 = new Vec3();
|
|
|
|
|
|
onLoad () {
|
|
|
@@ -59,14 +64,22 @@ export class GameStartMove extends Component {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Instantly move the camera down by `offset` units.
|
|
|
+ * Instantly move the camera down to show the reference line at bottom.
|
|
|
+ * Requires referenceLineNode to be set.
|
|
|
*/
|
|
|
public moveDownInstant () {
|
|
|
if (!this.cameraNode) return;
|
|
|
+
|
|
|
const pos = this.cameraNode.position.clone();
|
|
|
- pos.y -= this.offset;
|
|
|
- this.cameraNode.setPosition(pos);
|
|
|
- console.log('GameStartMove.moveDownInstant 镜头下移,当前位置:', pos);
|
|
|
+
|
|
|
+ // Calculate movement based on reference line position
|
|
|
+ const moveDistance = this.calculateMoveDistanceToShowLine();
|
|
|
+ if (moveDistance > 0) {
|
|
|
+ pos.y -= moveDistance;
|
|
|
+ this.cameraNode.setPosition(pos);
|
|
|
+ console.log('GameStartMove.moveDownInstant 镜头下移,当前位置:', pos);
|
|
|
+ }
|
|
|
+
|
|
|
// 镜头下移时显示Gray遮罩
|
|
|
if (this.grayNode) {
|
|
|
this.grayNode.active = true;
|
|
|
@@ -74,12 +87,19 @@ export class GameStartMove extends Component {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Smoothly move the camera back up by `offset` units using a tween.
|
|
|
+ * Smoothly move the camera back up using a tween to original position.
|
|
|
+ * Requires referenceLineNode to be set.
|
|
|
*/
|
|
|
public moveUpSmooth () {
|
|
|
if (!this.cameraNode) return;
|
|
|
+
|
|
|
const startPos = this.cameraNode.position.clone();
|
|
|
- const targetPos = new Vec3(startPos.x, startPos.y + this.offset, startPos.z);
|
|
|
+
|
|
|
+ // Calculate movement based on reference line position
|
|
|
+ const moveDistance = this.calculateMoveDistanceToShowLine();
|
|
|
+ if (moveDistance <= 0) return;
|
|
|
+
|
|
|
+ const targetPos = new Vec3(startPos.x, startPos.y + moveDistance, startPos.z);
|
|
|
// Stop any running tweens on this node to avoid conflicting animations.
|
|
|
console.log('GameStartMove.moveUpSmooth 镜头上移,开始执行');
|
|
|
Tween.stopAllByTarget(this.cameraNode);
|
|
|
@@ -92,72 +112,148 @@ export class GameStartMove extends Component {
|
|
|
|
|
|
|
|
|
|
|
|
+ /* ========= 私有辅助方法 ========= */
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Calculate the distance camera needs to move to show the reference line at the bottom of the view.
|
|
|
+ * @returns The movement distance in world units
|
|
|
+ */
|
|
|
+ private calculateMoveDistanceToShowLine(): number {
|
|
|
+ if (!this.referenceLineNode || !this.cameraNode) {
|
|
|
+ console.warn('GameStartMove.calculateMoveDistanceToShowLine: referenceLineNode or cameraNode not set');
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Get the camera component
|
|
|
+ const cameraComponent = this.cameraNode.getComponent(Camera);
|
|
|
+ if (!cameraComponent) {
|
|
|
+ console.warn('GameStartMove.calculateMoveDistanceToShowLine: Camera component not found');
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Get the reference line's world position
|
|
|
+ const lineWorldPos = this.referenceLineNode.getWorldPosition();
|
|
|
+
|
|
|
+ // Get camera's current world position
|
|
|
+ const cameraWorldPos = this.cameraNode.getWorldPosition();
|
|
|
+
|
|
|
+ // Calculate camera's view height in world units
|
|
|
+ // For orthographic camera, orthoHeight represents half of the view height
|
|
|
+ const cameraViewHalfHeight = cameraComponent.orthoHeight;
|
|
|
+
|
|
|
+ // Calculate the distance to move camera so that the line appears at the bottom
|
|
|
+ // We want: cameraWorldPos.y - cameraViewHalfHeight = lineWorldPos.y
|
|
|
+ // So: moveDistance = cameraWorldPos.y - lineWorldPos.y - cameraViewHalfHeight
|
|
|
+ const moveDistance = cameraWorldPos.y - lineWorldPos.y - cameraViewHalfHeight;
|
|
|
+
|
|
|
+ console.log('GameStartMove.calculateMoveDistanceToShowLine 计算移动距离:', {
|
|
|
+ lineWorldPos: lineWorldPos,
|
|
|
+ cameraWorldPos: cameraWorldPos,
|
|
|
+ cameraViewHalfHeight: cameraViewHalfHeight,
|
|
|
+ moveDistance: moveDistance
|
|
|
+ });
|
|
|
+
|
|
|
+ return Math.max(0, moveDistance); // Ensure we don't move in wrong direction
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取参考线在diban父节点坐标系中的位置和diban高度
|
|
|
+ * @returns 包含referenceLineLocalPos和dibanHeight的对象,如果节点未设置则返回null
|
|
|
+ */
|
|
|
+ private getReferenceLinePositionAndDibanHeight(): { referenceLineLocalPos: Vec3, dibanHeight: number } | null {
|
|
|
+ if (!this.dibanNode || !this.referenceLineNode) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取参考线的世界位置
|
|
|
+ const referenceLineWorldPos = this.referenceLineNode.getWorldPosition();
|
|
|
+
|
|
|
+ // 将参考线的世界位置转换为diban父节点的本地坐标
|
|
|
+ const referenceLineLocalPos = new Vec3();
|
|
|
+ this.dibanNode.parent.getComponent(UITransform).convertToNodeSpaceAR(referenceLineWorldPos, referenceLineLocalPos);
|
|
|
+
|
|
|
+ // 获取diban高度
|
|
|
+ const dibanUITransform = this.dibanNode.getComponent(UITransform);
|
|
|
+ const dibanHeight = dibanUITransform ? dibanUITransform.height : 0;
|
|
|
+
|
|
|
+ return { referenceLineLocalPos, dibanHeight };
|
|
|
+ }
|
|
|
+
|
|
|
/* ========= 高级动画方法 ========= */
|
|
|
|
|
|
/**
|
|
|
* 上滑 diban节点,进入备战状态。同时镜头下移。
|
|
|
- * @param distance 向上移动距离,默认 300
|
|
|
* @param duration 动画时长,默认 0.3s
|
|
|
*/
|
|
|
- public slideUpFromBottom(distance: number = 300, duration: number = 0.3) {
|
|
|
- console.log('GameStartMove.slideUpFromBottom 开始执行');
|
|
|
+ public slideUpFromBottom(duration: number = 0.3) {
|
|
|
|
|
|
- // 使用装饰器属性中的diban节点
|
|
|
- if (!this.dibanNode) {
|
|
|
- console.warn('GameStartMove.slideUpFromBottom diban节点未设置');
|
|
|
+ // 显示diban节点
|
|
|
+ this.dibanNode.active = true;
|
|
|
+
|
|
|
+ // 获取参考线位置和diban高度
|
|
|
+ const positionData = this.getReferenceLinePositionAndDibanHeight();
|
|
|
+ if (!positionData) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- // 保存diban的原始位置(如果还没保存的话)
|
|
|
- if (this._originalDibanPos.equals(Vec3.ZERO)) {
|
|
|
- this._originalDibanPos.set(this.dibanNode.position);
|
|
|
- }
|
|
|
+ const { referenceLineLocalPos, dibanHeight } = positionData;
|
|
|
|
|
|
- // 设置diban初始位置(在屏幕下方)
|
|
|
- const startPos = this._originalDibanPos.clone();
|
|
|
- startPos.y -= distance;
|
|
|
- this.dibanNode.setPosition(startPos);
|
|
|
+ // 计算diban的初始位置:diban顶部与参考线对齐
|
|
|
+ const startPos = new Vec3(this.dibanNode.position.x, referenceLineLocalPos.y - dibanHeight / 2, this.dibanNode.position.z);
|
|
|
|
|
|
- console.log('GameStartMove.slideUpFromBottom diban初始位置:', startPos);
|
|
|
- console.log('GameStartMove.slideUpFromBottom diban目标位置:', this._originalDibanPos);
|
|
|
+ // 计算目标位置:diban底部与参考线对齐
|
|
|
+ const targetPos = new Vec3(this.dibanNode.position.x, referenceLineLocalPos.y + dibanHeight / 2, this.dibanNode.position.z);
|
|
|
|
|
|
+ // 设置diban初始位置
|
|
|
+ this.dibanNode.setPosition(startPos);
|
|
|
+
|
|
|
// 停止任何正在运行的动画
|
|
|
Tween.stopAllByTarget(this.dibanNode);
|
|
|
-
|
|
|
+
|
|
|
// 执行上滑动画
|
|
|
tween(this.dibanNode)
|
|
|
- .to(duration, { position: this._originalDibanPos }, { easing: 'quadOut' })
|
|
|
+ .to(duration, { position: targetPos }, { easing: 'quadInOut' })
|
|
|
.call(() => {
|
|
|
- console.log('GameStartMove.slideUpFromBottom diban上滑动画完成');
|
|
|
+ const animationEndTime = Date.now();
|
|
|
})
|
|
|
.start();
|
|
|
|
|
|
// 同时执行camera下移动画
|
|
|
this.moveDownInstant();
|
|
|
-
|
|
|
- console.log('GameStartMove.slideUpFromBottom diban上滑动画已启动');
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 下滑 diban节点,结束备战进入playing 状态。
|
|
|
- * @param distance 向下移动距离,默认 300
|
|
|
* @param duration 动画时长,默认 0.3s
|
|
|
*/
|
|
|
- public slideDibanDownAndHide(distance: number = 300, duration: number = 0.3) {
|
|
|
- console.log('GameStartMove.slideDibanDownAndHide 开始执行');
|
|
|
-
|
|
|
+ public slideDibanDownAndHide(duration: number = 0.3) {
|
|
|
// 使用装饰器属性中的diban节点
|
|
|
if (!this.dibanNode) {
|
|
|
console.warn('GameStartMove.slideDibanDownAndHide diban节点未设置');
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ // 检查参考线节点
|
|
|
+ if (!this.referenceLineNode) {
|
|
|
+ console.warn('GameStartMove.slideDibanDownAndHide 参考线节点未设置');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
// 获取当前位置
|
|
|
const currentPos = this.dibanNode.position.clone();
|
|
|
console.log('GameStartMove.slideDibanDownAndHide diban当前位置:', currentPos);
|
|
|
|
|
|
- // 计算目标位置(向下移动)
|
|
|
- const targetPos = new Vec3(currentPos.x, currentPos.y - distance, currentPos.z);
|
|
|
+ // 获取参考线位置和diban高度
|
|
|
+ const positionData = this.getReferenceLinePositionAndDibanHeight();
|
|
|
+ if (!positionData) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const { referenceLineLocalPos, dibanHeight } = positionData;
|
|
|
+
|
|
|
+ // 计算目标位置:diban顶部与参考线对齐(下滑到初始位置)
|
|
|
+ const targetPos = new Vec3(currentPos.x, referenceLineLocalPos.y - dibanHeight / 2, currentPos.z);
|
|
|
+
|
|
|
console.log('GameStartMove.slideDibanDownAndHide diban目标位置:', targetPos);
|
|
|
|
|
|
// 停止任何正在运行的动画
|
|
|
@@ -172,6 +268,8 @@ export class GameStartMove extends Component {
|
|
|
if (this.grayNode) {
|
|
|
this.grayNode.active = false;
|
|
|
}
|
|
|
+ // 动画完成后隐藏diban节点
|
|
|
+ this.dibanNode.active = false;
|
|
|
})
|
|
|
.start();
|
|
|
|