const { ccclass, property } = cc._decorator; /** * 飞item组件 * - item使用容器存储,可复用,组件的节点被销毁时,销毁所有item * - 流程: * - 把节点在范围内随机展开,移动到指定位置 * - 数值优先使用通过事件传递的值,没有则使用装饰器上的默认值 * @author 薛鸿潇 */ @ccclass export default class FlyNode extends cc.Component { @property({ displayName: '起始阶段消耗时间' }) private start_move_time: number = 0.1; @property({ displayName: '结束阶段消耗时间' }) private end_move_time: number = 0.3; // @property({ displayName: 'item缩放比率' }) // private item_scale: number = 0.2; @property({ displayName: 'item默认数量' }) private item_count: number = 10; /** 组件数据 */ private fly_data = { /** 节点的父节点 */ node_p: null, /** 节点数量 */ item_count: this.item_count, /** 节点大小 */ item_scale: [0.3, 1], /** 节点纹理 */ item_sf: null, /** 起始位置 */ start_pos: cc.Vec2.ZERO, /** 结束位置 */ end_pos: cc.Vec2.ZERO, /** 完成回调 */ complete_call: null, } /** item父节点 */ private node_fly: cc.Node = null; /** item容器 */ private arr_item: Array = []; onLoad() { this.node.on('ui-fly-node', this.getNodeProgress, this); } /** * 加载 小号图标组 * @param _fly_data 数据内容 */ private getNodeProgress(_fly_data: any) { // 数据整理node_p, item_sf: cc.SpriteFrame, item_count: number, start_pos: cc.Vec2 = cc.Vec2.ZERO, item_scale: number = 1 // this.fly_data = _fly_data; if (_fly_data.node_p) this.fly_data.node_p = _fly_data.node_p; if (_fly_data.item_count) this.fly_data.item_count = _fly_data.item_count; if (_fly_data.item_scale) this.fly_data.item_scale = _fly_data.item_scale; if (_fly_data.item_sf) this.fly_data.item_sf = _fly_data.item_sf; if (_fly_data.start_pos) this.fly_data.start_pos = _fly_data.start_pos; if (_fly_data.end_pos) this.fly_data.end_pos = _fly_data.end_pos; if (_fly_data.complete_call) this.fly_data.complete_call = _fly_data.complete_call; let node_p = this.fly_data.node_p; const item_count = this.fly_data.item_count; const item_scale = this.fly_data.item_scale; let item_sf = this.fly_data.item_sf; let start_pos = this.fly_data.start_pos; // 创建节点 if (!this.node_fly) { this.node_fly = new cc.Node('node_fly'); this.node_fly.parent = node_p; } for (let i = 0; i < item_count; i++) { let node_item = this.arr_item.shift(); if (!node_item || (node_item && node_item.parent)) { // 无item 或者item存在,但有父节点【表示正在运行中】 node_item = new cc.Node('node_item'); this.arr_item.push(node_item); } node_item.stopAllActions(); node_item.parent = this.node_fly; node_item.setPosition(start_pos); // // 创建位置 node_item.angle = this.range(-45, 45, true); let new_scale = this.range(item_scale[0], item_scale[1], false); node_item.scale = new_scale; // 偏移位置计算-新 let dir = cc.v2(this.range(-1, 1, false), this.range(-1, 1, false)); dir = dir.normalize(); let deltaInit = cc.v2(this.range(10, 80, false) * dir.x, this.range(10, 80, false) * dir.y); let initPos = start_pos.add(deltaInit); // node_item.setPosition(initPos); // 纹理 let spr_item = node_item.getComponent(cc.Sprite) || node_item.addComponent(cc.Sprite); spr_item.spriteFrame = item_sf; // 执行动画 this.movePos(node_item, initPos); } } /** * 移动到起始位置 * @param node_item * @param initPos */ private movePos(node_item, initPos) { let new_start_move_time = this.range(0.3, 1, false); //this.start_move_time let start_pos = cc.tween().to(new_start_move_time, { position: new cc.Vec2(initPos) }, { easing: 'sineOut' }); let dt1 = cc.tween().delay(this.start_move_time * 1.5); // this.end_move_time // 结束阶段效果 let end_pos = cc.tween().to(this.end_move_time, { position: this.fly_data.end_pos }, { easing: 'sineOut' }) let end_scale = cc.tween().to(this.end_move_time, { scale: 1 }); let end_angle = cc.tween().to(this.end_move_time, { angle: 0 }); let parallel1 = cc.tween().parallel(end_pos, end_scale, end_angle); let call1 = cc.tween().call(() => { this.fly_data.complete_call && this.fly_data.complete_call(); this.fly_data.complete_call = null; this.arr_item.push(node_item); node_item.removeFromParent(); }); cc.tween(node_item).then(start_pos).then(dt1).then(parallel1).then(call1).start(); } /** * * @param min * @param max * @param isInt * @returns */ private range(min: number, max: number, isInt: boolean = true): number { //return min + Math.ceil(Math.random() * 1000) % (max - min); //不包含最大值 let del: number = max - min; if (del > 0) { let val: number = min + Math.random() * 0xffffff % del if (isInt) { return Math.floor(val); } return val } return min; } onDestroy() { const item_count = this.arr_item.length for (let i = 0; i < item_count; i++) { if (cc.isValid(this.arr_item[0])) { this.arr_item[0].destroy(); this.arr_item.shift(); } } } // update (dt) {} }