闲着也是闲着,写了个点击效果组件,简简单单针不戳

一个简简单单的点击效果组件

在线预览:Cocos Creator | eazax-cases

效果图:无(macOS 录制的 GIF 太大了,上传不了,淦,自己在线预览吧)

组件图:

组件地址:components/TouchEffect.ts · 陈皮皮/Eazax Cocos 游戏开发工具包 - Gitee.com

组件代码:

const { ccclass, property } = cc._decorator;

/**
 * 点击效果
 * @author 陈皮皮 (ifaswind)
 * @version 20220214
 * @see TouchEffect.ts https://gitee.com/ifaswind/eazax-ccc/blob/master/components/TouchEffect.ts
 */
@ccclass
export default class TouchEffect extends cc.Component {

    @property({ type: cc.Prefab, displayName: CC_DEV && '效果节点预制体' })
    protected effectPrefab: cc.Prefab = null;

    @property({ type: cc.Node, displayName: CC_DEV && '效果节点容器' })
    protected effectContainer: cc.Node = null;

    @property({ displayName: CC_DEV && '持续时间' })
    protected duration: number = 0.5;

    @property({ displayName: CC_DEV && '触发间隔' })
    protected interval: number = 0.5;

    @property({ displayName: CC_DEV && '同时存在最大数量' })
    protected maxQuantity: number = 20;

    @property({ displayName: CC_DEV && '允许滑动触发', tooltip: CC_DEV && '希望你知道你在做什么,试着调整触发时间和同时存在最大数量' })
    protected triggerByMoving: boolean = false;

    @property({ displayName: CC_DEV && '使用节点池缓存', tooltip: CC_DEV && '提高播放大量效果时的性能' })
    protected useNodePool: boolean = false;

    @property({ visible() { return this.useNodePool; }, displayName: CC_DEV && '节点池缓存数量上限', tooltip: CC_DEV && '看着点内存' })
    protected nodePoolLimit: number = 20;

    /**
     * 当前存在效果数量
     */
    protected curCount: number = 0;

    /**
     * 上一个效果触发时间
     */
    protected lastTriggerTime: number = 0;

    /**
     * 节点池
     */
    protected nodePool: cc.NodePool = new cc.NodePool();

    /**
     * 生命周期:加载
     */
    protected onLoad() {
        this.registerEvent();
    }

    /**
     * 生命周期:销毁
     */
    protected onDestroy() {
        this.unregisterEvent();
    }

    /**
     * 注册事件
     */
    protected registerEvent() {
        this.node.on(cc.Node.EventType.TOUCH_START, this.onTouchStart, this);
        this.node.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
        // 取消事件吞噬
        this.setSwallowTouches(false);
    }

    /**
     * 反注册事件
     */
    protected unregisterEvent() {
        this.node.off(cc.Node.EventType.TOUCH_START, this.onTouchStart, this);
        this.node.off(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
    }

    /**
     * 点击开始回调
     * @param event 
     */
    protected onTouchStart(event: cc.Event.EventTouch) {
        this.playEffect(event.getLocation());
    }

    /**
     * 点击移动回调
     * @param event 
     */
    protected onTouchMove(event: cc.Event.EventTouch) {
        if (!this.triggerByMoving) {
            return;
        }
        this.playEffect(event.getLocation());
    }

    /**
     * 播放效果
     * @param pos 
     */
    protected playEffect(pos: cc.Vec2) {
        const now = Date.now();
        if (this.curCount >= this.maxQuantity ||
            this.lastTriggerTime > (now - this.interval * 1000)) {
            return;
        }
        this.lastTriggerTime = now;
        this.curCount++;
        // 创建节点
        let node: cc.Node = null;
        if (this.nodePool.size() > 0) {
            node = this.nodePool.get();
        } else {
            node = cc.instantiate(this.effectPrefab);
        }
        // 设置节点
        const container = this.effectContainer || this.node;
        node.setParent(container);
        node.setPosition(container.convertToNodeSpaceAR(pos));
        // 播放动画
        node.opacity = 255;
        cc.tween(node)
            .to(this.duration, { opacity: 0 })
            .call(() => this.recycleEffect(node))
            .start();
    }

    /**
     * 回收效果
     * @param node 
     */
    protected recycleEffect(node: cc.Node) {
        this.curCount--;
        // 回收或者销毁
        if (this.useNodePool && this.nodePool.size() < this.nodePoolLimit) {
            this.nodePool.put(node);
        } else {
            node.destroy();
        }
    }

    /**
     * 设置节点是否吞噬点击事件
     * @param swallow 状态
     */
    protected setSwallowTouches(swallow: boolean) {
        this.node._touchListener && this.node._touchListener.setSwallowTouches(swallow);
    }

}

好,那就这样吧。

16赞


皮神,太多项目了,不知道这个组件的预览入口是哪个 :sweat_smile:

4赞

点击效果,当然是点击就有的效果,哈哈哈哈哈哈哈

提个建议,皮佬,看看今天的日子。。。。 :grinning:
话说这个效果在我这彩笔手上很花

是不是要把效果换成:heart:哈哈哈

:grinning:那肯定的啊

有了哈哈哈哈哈

2赞

:+1:新需求来了:改成TT图片,然后淡出改成TT破了 :joy:

这需求我不接!!!拒绝!!!

哈哈,你这纯折磨皮神,你想想为啥他今天这么闲 :shushing_face:

小姐姐跑路过节去了,所以没人做资源? :grinning:

tsl,用的还是label :clap:

太强了 mark

针~不~戳~

带带弟弟啊

哈哈哈,优秀

:laughing: :laughing: :laughing:
赞,皮神,妙呀

皮神牛逼 :grinning:

666666 mark 大佬牛

mark!!!