GameStartMove.ts 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  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 high-level animation methods for block selection mode transitions:
  8. * 1. enterBlockSelectionMode() – complete animation for entering block selection (camera down + UI slide up)
  9. * 2. exitBlockSelectionMode() – complete animation for exiting block selection (camera up + UI slide down)
  10. *
  11. * Also provides low-level methods for specific use cases:
  12. * - moveDownInstant() – instantly move the camera down by a fixed offset
  13. * - moveUpSmooth() – move the camera back up with a smooth tween animation
  14. * - slideUpFromBottom() – slide UI up from bottom
  15. * - slideDibanDownAndHide() – slide UI down and hide
  16. */
  17. @ccclass('GameStartMove')
  18. export class GameStartMove extends Component {
  19. /** The camera node to move. Defaults to the node the script is attached to. */
  20. @property({
  21. type: Node,
  22. tooltip: 'Camera node to move. Leave empty to use the current node.'
  23. })
  24. public cameraNode: Node = null;
  25. /** Offset (in pixels/units) for one step of movement. */
  26. @property({ tooltip: 'Vertical offset for the camera movement.' })
  27. public offset: number = 182;
  28. /** Tween duration for the smooth move-up animation. */
  29. @property({ tooltip: 'Duration for the smooth move-up tween (seconds).' })
  30. public moveDuration: number = 0.4;
  31. private _originalPos: Vec3 = new Vec3();
  32. /** 需要下滑的 diban 节点(外部拖拽赋值) */
  33. @property({ type: Node, tooltip: 'diban 节点' })
  34. public dibanNode: Node = null;
  35. /** Gray遮罩节点 */
  36. @property({ type: Node, tooltip: 'Canvas/GameLevelUI/Gray节点' })
  37. public grayNode: Node = null;
  38. private _originalDibanPos: Vec3 = new Vec3();
  39. onLoad () {
  40. // Use self node if cameraNode not assigned via the editor.
  41. if (!this.cameraNode) {
  42. this.cameraNode = this.node;
  43. }
  44. // Save initial position so we can always restore relative to it.
  45. this._originalPos.set(this.cameraNode.position);
  46. // Save diban original position if dibanNode is assigned
  47. if (this.dibanNode) {
  48. this._originalDibanPos.set(this.dibanNode.position);
  49. }
  50. }
  51. /**
  52. * Instantly move the camera down by `offset` units.
  53. */
  54. public moveDownInstant () {
  55. if (!this.cameraNode) return;
  56. const pos = this.cameraNode.position.clone();
  57. pos.y -= this.offset;
  58. this.cameraNode.setPosition(pos);
  59. console.log('GameStartMove.moveDownInstant 镜头下移,当前位置:', pos);
  60. // 镜头下移时显示Gray遮罩
  61. if (this.grayNode) {
  62. this.grayNode.active = true;
  63. }
  64. }
  65. /**
  66. * Smoothly move the camera back up by `offset` units using a tween.
  67. */
  68. public moveUpSmooth () {
  69. if (!this.cameraNode) return;
  70. const startPos = this.cameraNode.position.clone();
  71. const targetPos = new Vec3(startPos.x, startPos.y + this.offset, startPos.z);
  72. // Stop any running tweens on this node to avoid conflicting animations.
  73. console.log('GameStartMove.moveUpSmooth 镜头上移,开始执行');
  74. Tween.stopAllByTarget(this.cameraNode);
  75. tween(this.cameraNode)
  76. .to(this.moveDuration, { position: targetPos }, { easing: 'quadOut' })
  77. .start();
  78. }
  79. /* ========= 高级动画方法 ========= */
  80. /**
  81. * 上滑 diban节点,进入备战状态。同时镜头下移。
  82. * @param distance 向上移动距离,默认 300
  83. * @param duration 动画时长,默认 0.3s
  84. */
  85. public slideUpFromBottom(distance: number = 300, duration: number = 0.3) {
  86. console.log('GameStartMove.slideUpFromBottom 开始执行');
  87. // 使用装饰器属性中的diban节点
  88. if (!this.dibanNode) {
  89. console.warn('GameStartMove.slideUpFromBottom diban节点未设置');
  90. return;
  91. }
  92. // 保存diban的原始位置(如果还没保存的话)
  93. if (this._originalDibanPos.equals(Vec3.ZERO)) {
  94. this._originalDibanPos.set(this.dibanNode.position);
  95. }
  96. // 设置diban初始位置(在屏幕下方)
  97. const startPos = this._originalDibanPos.clone();
  98. startPos.y -= distance;
  99. this.dibanNode.setPosition(startPos);
  100. console.log('GameStartMove.slideUpFromBottom diban初始位置:', startPos);
  101. console.log('GameStartMove.slideUpFromBottom diban目标位置:', this._originalDibanPos);
  102. // 停止任何正在运行的动画
  103. Tween.stopAllByTarget(this.dibanNode);
  104. // 执行上滑动画
  105. tween(this.dibanNode)
  106. .to(duration, { position: this._originalDibanPos }, { easing: 'quadOut' })
  107. .call(() => {
  108. console.log('GameStartMove.slideUpFromBottom diban上滑动画完成');
  109. })
  110. .start();
  111. // 同时执行camera下移动画
  112. this.moveDownInstant();
  113. console.log('GameStartMove.slideUpFromBottom diban上滑动画已启动');
  114. }
  115. /**
  116. * 下滑 diban节点,结束备战进入playing 状态。
  117. * @param distance 向下移动距离,默认 300
  118. * @param duration 动画时长,默认 0.3s
  119. */
  120. public slideDibanDownAndHide(distance: number = 300, duration: number = 0.3) {
  121. console.log('GameStartMove.slideDibanDownAndHide 开始执行');
  122. // 使用装饰器属性中的diban节点
  123. if (!this.dibanNode) {
  124. console.warn('GameStartMove.slideDibanDownAndHide diban节点未设置');
  125. return;
  126. }
  127. // 获取当前位置
  128. const currentPos = this.dibanNode.position.clone();
  129. console.log('GameStartMove.slideDibanDownAndHide diban当前位置:', currentPos);
  130. // 计算目标位置(向下移动)
  131. const targetPos = new Vec3(currentPos.x, currentPos.y - distance, currentPos.z);
  132. console.log('GameStartMove.slideDibanDownAndHide diban目标位置:', targetPos);
  133. // 停止任何正在运行的动画
  134. Tween.stopAllByTarget(this.dibanNode);
  135. // 执行下滑动画
  136. tween(this.dibanNode)
  137. .to(duration, { position: targetPos }, { easing: 'quadOut' })
  138. .call(() => {
  139. console.log('GameStartMove.slideDibanDownAndHide diban下滑动画完成');
  140. // 动画完成时隐藏Gray遮罩
  141. if (this.grayNode) {
  142. this.grayNode.active = false;
  143. }
  144. })
  145. .start();
  146. // 同时执行camera上移动画
  147. this.moveUpSmooth();
  148. console.log('GameStartMove.slideDibanDownAndHide diban下滑动画已启动');
  149. }
  150. }