123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- import { Component, EventTouch, Node, Prefab, UIOpacity, UITransform, Vec3, Widget, _decorator, easing, instantiate, tween, v3 } from 'cc';
- const { ccclass, requireComponent } = _decorator;
- @ccclass('RewardFly')
- @requireComponent(UITransform)
- export class RewardFly extends Component {
- protected onLoad() {
- //this.node.on(Node.EventType.TOUCH_START, function (event: EventTouch) {
- //event.propagationStopped = true;
- //event.preventSwallow = true;
- //}, this, true);
- }
- protected onDisable() {
- this.node.destroyAllChildren();
- }
- private convertToNodeSpaceAR(target: Node | Vec3) {
- if (target instanceof Node) {
- return this.node.getComponent(UITransform).convertToNodeSpaceAR(target.getComponent(UITransform).convertToWorldSpaceAR(Vec3.ZERO));
- }
- return this.node.getComponent(UITransform).convertToNodeSpaceAR(target);
- }
- public add(opts: {
- /**物品 */
- item: Prefab | Node,
- /**物品数量 */
- count: number,
- /**起始位置(节点或世界坐标) */
- start: Node | Vec3,
- /**终点位置(节点或世界坐标) */
- end: Node | Vec3,
- /**起点炸开的范围[x, y], 默认[100, 100] */
- startRange?: [number, number],
- /**终点偏移的范围[x, y], 默认[0, 0] */
- endOffset?: [number, number],
- /**开始接触 */
- onBegin?: (nodeCopy: Node | null) => any,
- /**持续接触(包括开始) */
- onContact?: (nodeCopy: Node | null) => any,
- /**动画结束 */
- onFinish?: (nodeCopy: Node | null) => any
- /**拷贝highlightArea或end至当前节点下, 优先highlightArea */
- highlight?: boolean,
- /**高亮区域,依赖highlight开启 */
- highlightArea?: Node,
- /**高亮位置偏移[x, y],依赖highlight开启, 默认[0, 0] */
- highlightOffset?: [number, number],
- }) {
- const startPos = this.convertToNodeSpaceAR(opts.start);
- const endPos = this.convertToNodeSpaceAR(opts.end);
- if (opts.endOffset) {
- endPos.add3f(opts.endOffset[0], opts.endOffset[1], 0);
- }
- let nodeCopy: Node = null;
- if (opts.highlight) {
- if (opts.highlightOffset) {
- endPos.add3f(opts.highlightOffset[0], opts.highlightOffset[1], 0);
- }
- if (opts.highlightArea) {
- const endAreaPos = this.convertToNodeSpaceAR(opts.highlightArea);
- if (opts.highlightOffset) {
- endAreaPos.add3f(opts.highlightOffset[0], opts.highlightOffset[1], 0);
- }
- nodeCopy = instantiate(opts.highlightArea);
- nodeCopy.getComponent(Widget)?.destroy();
- nodeCopy.setParent(this.node);
- nodeCopy.setPosition(endAreaPos);
- } else if (Node.isNode(opts.end)) {
- nodeCopy = instantiate(opts.end);
- nodeCopy.getComponent(Widget)?.destroy();
- nodeCopy.setParent(this.node);
- nodeCopy.setPosition(endPos);
- }
- }
- for (let index = 0; index < opts.count; index++) {
- const aniNode = instantiate(opts.item) as Node;
- aniNode.setPosition(startPos);
- aniNode.setParent(this.node);
- // 炸开位置
- const midPos = v3(startPos.x, startPos.y, 0);
- midPos.x += (Math.random() * 2 - 1) * (opts.startRange ? opts.startRange[0] : 100);
- midPos.y += (Math.random() * 2 - 1) * (opts.startRange ? opts.startRange[1] : 100);
- // 执行动画
- (aniNode.getComponent(UIOpacity) || aniNode.addComponent(UIOpacity)).opacity = 0;
- tween(aniNode)
- .delay(index * 0.025)
- .call(() => {
- aniNode.getComponent(UIOpacity).opacity = 200;
- tween(aniNode.getComponent(UIOpacity))
- .to(0.4, { opacity: 255 }, { easing: easing.expoOut })
- .start();
- })
- .to(0.4, { position: midPos }, { easing: easing.expoOut })
- .call(() => {
- tween(aniNode.getComponent(UIOpacity))
- .delay(0.5)
- .to(0.1, { opacity: 70 })
- .start();
- })
- .to(0.6, { position: endPos }, { easing: easing.expoIn })
- .call(() => {
- if (index === 0) {
- // 结束节点缩放
- if (nodeCopy) {
- const scale = v3(nodeCopy.scale);
- tween(nodeCopy)
- .to(0.1, { scale: v3(scale.x * 1.3, scale.y * 1.3) })
- .delay(0.025 * Math.max(opts.count, 4))
- .to(0.1, { scale: scale })
- .call(() => {
- // 结束节点透明销毁
- const uiOpacity = nodeCopy.getComponent(UIOpacity) || nodeCopy.addComponent(UIOpacity);
- tween(uiOpacity)
- .to(0.1, { opacity: uiOpacity.opacity * 0.3 })
- .call(() => nodeCopy.destroy())
- .start();
- })
- .start();
- }
- opts.onBegin && opts.onBegin(nodeCopy);
- }
- opts.onContact && opts.onContact(nodeCopy);
- })
- .delay(0.01)
- .call(() => {
- aniNode.destroy();
- if (index === opts.count - 1) {
- opts.onFinish && opts.onFinish(nodeCopy);
- }
- }).start();
- }
- }
- }
|