import { _decorator, Component, Node, Vec3, tween, Tween } from 'cc'; const { ccclass, property } = _decorator; /** * GameStartMove * * This component is expected to be attached to the main camera node. * It provides two public helper methods that other scripts can call: * 1. moveDownInstant() – instantly move the camera down by a fixed offset * 2. moveUpSmooth() – move the camera back up with a smooth tween animation */ @ccclass('GameStartMove') export class GameStartMove extends Component { /** The camera node to move. Defaults to the node the script is attached to. */ @property({ type: Node, tooltip: 'Camera node to move. Leave empty to use the current node.' }) 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; /** Tween duration for the smooth move-up animation. */ @property({ tooltip: 'Duration for the smooth move-up tween (seconds).' }) public moveDuration: number = 0.4; private _originalPos: Vec3 = new Vec3(); onLoad () { // Use self node if cameraNode not assigned via the editor. if (!this.cameraNode) { this.cameraNode = this.node; } // Save initial position so we can always restore relative to it. this._originalPos.set(this.cameraNode.position); } /** * Instantly move the camera down by `offset` units. */ public moveDownInstant () { if (!this.cameraNode) return; const pos = this.cameraNode.position.clone(); pos.y -= this.offset; this.cameraNode.setPosition(pos); } /** * Smoothly move the camera back up by `offset` units using a tween. */ public moveUpSmooth () { if (!this.cameraNode) return; const startPos = this.cameraNode.position.clone(); const targetPos = new Vec3(startPos.x, startPos.y + this.offset, startPos.z); // Stop any running tweens on this node to avoid conflicting animations. Tween.stopAllByTarget(this.cameraNode); tween(this.cameraNode) .to(this.moveDuration, { position: targetPos }, { easing: 'quadOut' }) .start(); } /* ========= BlockSelectionUI 动画 ========= */ /** BlockSelectionUI 根节点(外部在编辑器拖拽赋值) */ @property({ type: Node, tooltip: 'BlockSelectionUI 根节点' }) public blockSelectionUI: Node = null; /** BlockSelectionUI 中需要下滑的 diban 节点(外部拖拽赋值) */ @property({ type: Node, tooltip: 'BlockSelectionUI 中的 diban 节点' }) public dibanNode: Node = null; /** * 下滑 diban 并在动画结束后隐藏 BlockSelectionUI。 * @param distance 向下移动距离,默认 300 * @param duration 动画时长,默认 0.3s */ public slideDibanDownAndHide(distance: number = 300, duration: number = 0.3) { if (!this.dibanNode || !this.blockSelectionUI) return; const originalPos = this.dibanNode.position.clone(); // 停止现有 tween Tween.stopAllByTarget(this.dibanNode); tween(this.dibanNode) .to(duration, { position: new Vec3(originalPos.x, originalPos.y - distance, originalPos.z) }, { easing: 'quadIn' }) .call(() => { this.blockSelectionUI.active = false; this.dibanNode.setPosition(originalPos); }) .start(); } }