GameStartMove.ts 3.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. import { _decorator, Component, Node, Vec3, tween, Tween } from 'cc';
  2. const { ccclass, property } = _decorator;
  3. /**
  4. * GameStartMove
  5. *
  6. * This component is expected to be attached to the main camera node.
  7. * It provides two public helper methods that other scripts can call:
  8. * 1. moveDownInstant() – instantly move the camera down by a fixed offset
  9. * 2. moveUpSmooth() – move the camera back up with a smooth tween animation
  10. */
  11. @ccclass('GameStartMove')
  12. export class GameStartMove extends Component {
  13. /** The camera node to move. Defaults to the node the script is attached to. */
  14. @property({
  15. type: Node,
  16. tooltip: 'Camera node to move. Leave empty to use the current node.'
  17. })
  18. public cameraNode: Node = null;
  19. /** Offset (in pixels/units) for one step of movement. */
  20. @property({ tooltip: 'Vertical offset for the camera movement.' })
  21. public offset: number = 182;
  22. /** Tween duration for the smooth move-up animation. */
  23. @property({ tooltip: 'Duration for the smooth move-up tween (seconds).' })
  24. public moveDuration: number = 0.4;
  25. private _originalPos: Vec3 = new Vec3();
  26. onLoad () {
  27. // Use self node if cameraNode not assigned via the editor.
  28. if (!this.cameraNode) {
  29. this.cameraNode = this.node;
  30. }
  31. // Save initial position so we can always restore relative to it.
  32. this._originalPos.set(this.cameraNode.position);
  33. }
  34. /**
  35. * Instantly move the camera down by `offset` units.
  36. */
  37. public moveDownInstant () {
  38. if (!this.cameraNode) return;
  39. const pos = this.cameraNode.position.clone();
  40. pos.y -= this.offset;
  41. this.cameraNode.setPosition(pos);
  42. }
  43. /**
  44. * Smoothly move the camera back up by `offset` units using a tween.
  45. */
  46. public moveUpSmooth () {
  47. if (!this.cameraNode) return;
  48. const startPos = this.cameraNode.position.clone();
  49. const targetPos = new Vec3(startPos.x, startPos.y + this.offset, startPos.z);
  50. // Stop any running tweens on this node to avoid conflicting animations.
  51. Tween.stopAllByTarget(this.cameraNode);
  52. tween(this.cameraNode)
  53. .to(this.moveDuration, { position: targetPos }, { easing: 'quadOut' })
  54. .start();
  55. }
  56. /* ========= BlockSelectionUI 动画 ========= */
  57. /** BlockSelectionUI 根节点(外部在编辑器拖拽赋值) */
  58. @property({ type: Node, tooltip: 'BlockSelectionUI 根节点' })
  59. public blockSelectionUI: Node = null;
  60. /** BlockSelectionUI 中需要下滑的 diban 节点(外部拖拽赋值) */
  61. @property({ type: Node, tooltip: 'BlockSelectionUI 中的 diban 节点' })
  62. public dibanNode: Node = null;
  63. /**
  64. * 下滑 diban 并在动画结束后隐藏 BlockSelectionUI。
  65. * @param distance 向下移动距离,默认 300
  66. * @param duration 动画时长,默认 0.3s
  67. */
  68. public slideDibanDownAndHide(distance: number = 300, duration: number = 0.3) {
  69. if (!this.dibanNode || !this.blockSelectionUI) return;
  70. const originalPos = this.dibanNode.position.clone();
  71. // 停止现有 tween
  72. Tween.stopAllByTarget(this.dibanNode);
  73. tween(this.dibanNode)
  74. .to(duration, { position: new Vec3(originalPos.x, originalPos.y - distance, originalPos.z) }, { easing: 'quadIn' })
  75. .call(() => {
  76. this.blockSelectionUI.active = false;
  77. this.dibanNode.setPosition(originalPos);
  78. })
  79. .start();
  80. }
  81. }