FlyNode.ts 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. const { ccclass, property } = cc._decorator;
  2. /**
  3. * 飞item组件
  4. * - item使用容器存储,可复用,组件的节点被销毁时,销毁所有item
  5. * - 流程:
  6. * - 把节点在范围内随机展开,移动到指定位置
  7. * - 数值优先使用通过事件传递的值,没有则使用装饰器上的默认值
  8. * @author 薛鸿潇
  9. */
  10. @ccclass
  11. export default class FlyNode extends cc.Component {
  12. @property({ displayName: '起始阶段消耗时间' })
  13. private start_move_time: number = 0.1;
  14. @property({ displayName: '结束阶段消耗时间' })
  15. private end_move_time: number = 0.3;
  16. // @property({ displayName: 'item缩放比率' })
  17. // private item_scale: number = 0.2;
  18. @property({ displayName: 'item默认数量' })
  19. private item_count: number = 10;
  20. /** 组件数据 */
  21. private fly_data = {
  22. /** 节点的父节点 */
  23. node_p: null,
  24. /** 节点数量 */
  25. item_count: this.item_count,
  26. /** 节点大小 */
  27. item_scale: [0.3, 1],
  28. /** 节点纹理 */
  29. item_sf: null,
  30. /** 起始位置 */
  31. start_pos: cc.Vec2.ZERO,
  32. /** 结束位置 */
  33. end_pos: cc.Vec2.ZERO,
  34. /** 完成回调 */
  35. complete_call: null,
  36. }
  37. /** item父节点 */
  38. private node_fly: cc.Node = null;
  39. /** item容器 */
  40. private arr_item: Array<cc.Node> = [];
  41. onLoad() {
  42. this.node.on('ui-fly-node', this.getNodeProgress, this);
  43. }
  44. /**
  45. * 加载 小号图标组
  46. * @param _fly_data 数据内容
  47. */
  48. private getNodeProgress(_fly_data: any) {
  49. // 数据整理node_p, item_sf: cc.SpriteFrame, item_count: number, start_pos: cc.Vec2 = cc.Vec2.ZERO, item_scale: number = 1
  50. // this.fly_data = _fly_data;
  51. if (_fly_data.node_p) this.fly_data.node_p = _fly_data.node_p;
  52. if (_fly_data.item_count) this.fly_data.item_count = _fly_data.item_count;
  53. if (_fly_data.item_scale) this.fly_data.item_scale = _fly_data.item_scale;
  54. if (_fly_data.item_sf) this.fly_data.item_sf = _fly_data.item_sf;
  55. if (_fly_data.start_pos) this.fly_data.start_pos = _fly_data.start_pos;
  56. if (_fly_data.end_pos) this.fly_data.end_pos = _fly_data.end_pos;
  57. if (_fly_data.complete_call) this.fly_data.complete_call = _fly_data.complete_call;
  58. let node_p = this.fly_data.node_p;
  59. const item_count = this.fly_data.item_count;
  60. const item_scale = this.fly_data.item_scale;
  61. let item_sf = this.fly_data.item_sf;
  62. let start_pos = this.fly_data.start_pos;
  63. // 创建节点
  64. if (!this.node_fly) {
  65. this.node_fly = new cc.Node('node_fly');
  66. this.node_fly.parent = node_p;
  67. }
  68. for (let i = 0; i < item_count; i++) {
  69. let node_item = this.arr_item.shift();
  70. if (!node_item || (node_item && node_item.parent)) {
  71. // 无item 或者item存在,但有父节点【表示正在运行中】
  72. node_item = new cc.Node('node_item');
  73. this.arr_item.push(node_item);
  74. }
  75. node_item.stopAllActions();
  76. node_item.parent = this.node_fly;
  77. node_item.setPosition(start_pos);
  78. // // 创建位置
  79. node_item.angle = this.range(-45, 45, true);
  80. let new_scale = this.range(item_scale[0], item_scale[1], false);
  81. node_item.scale = new_scale;
  82. // 偏移位置计算-新
  83. let dir = cc.v2(this.range(-1, 1, false), this.range(-1, 1, false));
  84. dir = dir.normalize();
  85. let deltaInit = cc.v2(this.range(10, 80, false) * dir.x, this.range(10, 80, false) * dir.y);
  86. let initPos = start_pos.add(deltaInit);
  87. // node_item.setPosition(initPos);
  88. // 纹理
  89. let spr_item = node_item.getComponent(cc.Sprite) || node_item.addComponent(cc.Sprite);
  90. spr_item.spriteFrame = item_sf;
  91. // 执行动画
  92. this.movePos(node_item, initPos);
  93. }
  94. }
  95. /**
  96. * 移动到起始位置
  97. * @param node_item
  98. * @param initPos
  99. */
  100. private movePos(node_item, initPos) {
  101. let new_start_move_time = this.range(0.3, 1, false);
  102. //this.start_move_time
  103. let start_pos = cc.tween().to(new_start_move_time, { position: new cc.Vec2(initPos) }, { easing: 'sineOut' });
  104. let dt1 = cc.tween().delay(this.start_move_time * 1.5);
  105. // this.end_move_time
  106. // 结束阶段效果
  107. let end_pos = cc.tween().to(this.end_move_time, { position: this.fly_data.end_pos }, { easing: 'sineOut' })
  108. let end_scale = cc.tween().to(this.end_move_time, { scale: 1 });
  109. let end_angle = cc.tween().to(this.end_move_time, { angle: 0 });
  110. let parallel1 = cc.tween().parallel(end_pos, end_scale, end_angle);
  111. let call1 = cc.tween().call(() => {
  112. this.fly_data.complete_call && this.fly_data.complete_call();
  113. this.fly_data.complete_call = null;
  114. this.arr_item.push(node_item);
  115. node_item.removeFromParent();
  116. });
  117. cc.tween(node_item).then(start_pos).then(dt1).then(parallel1).then(call1).start();
  118. }
  119. /**
  120. *
  121. * @param min
  122. * @param max
  123. * @param isInt
  124. * @returns
  125. */
  126. private range(min: number, max: number, isInt: boolean = true): number {
  127. //return min + Math.ceil(Math.random() * 1000) % (max - min); //不包含最大值
  128. let del: number = max - min;
  129. if (del > 0) {
  130. let val: number = min + Math.random() * 0xffffff % del
  131. if (isInt) {
  132. return Math.floor(val);
  133. }
  134. return val
  135. }
  136. return min;
  137. }
  138. onDestroy() {
  139. const item_count = this.arr_item.length
  140. for (let i = 0; i < item_count; i++) {
  141. if (cc.isValid(this.arr_item[0])) {
  142. this.arr_item[0].destroy();
  143. this.arr_item.shift();
  144. }
  145. }
  146. }
  147. // update (dt) {}
  148. }