Cocos Creator实战-使用帧动画实现点击屏幕效果

2,093 阅读3分钟

帧动画实现点击屏幕效果

涉及到的知识点

  • 帧动画制作
  • 预制资源制作
  • 对象池的使用
  • 触摸事件监听以及坐标转化
  • 动态加载预制资源并显示特效

帧动画制作

制作帧动画并设置帧事件 步骤如下:

  • 1、添加cc.Sprite.spriteFrame 属性,在不同的帧设置不同的图片
  • 2、选中最后一帧
  • 3、选中最后一帧后,点击插入帧事件,点击后会在最后一帧显示一个帧事件的节点
  • 4、双击帧事件节点设置回调函数以及回调的参数

注意图中的批注

  • 制作帧动画并设置帧事件

    制作帧动画并设置帧事件

  • 设置帧动画回调函数

    设置帧动画回调函数

  • 预制资源效果图

    预制资源效果图

  • 帧动画回调组件代码如下

帧动画事件回调后直接使用当前节点发送事件,事件中为自定义参数,这里关键参数obj 为当前播放动画的节点,回收时会使用此参数。

/**
 * @author Javen 
 * @copyright 2018-12-12 15:22:31 javendev@126.com 
 * @description 动画执行回调
 */


cc.Class({
    extends: cc.Component,

    // onLoad () {},

    // start () {},

    // update (dt) {},
    clickDone() {
        let node = this.node;
        this.node.emit('clickDone', {
            msg: '点击屏幕动画播放完成',
            obj: node,
        });
    },

});

预制资源制作

参考 Cocos Creator实战-使用粒子资源实现屏幕点击效果

对象池的使用

参考官方指南文档-使用对象池 以及 官方提供的案例

触摸事件监听以及坐标转化

参考 Cocos Creator实战-使用粒子资源实现屏幕点击效果

动态加载预制资源并显示特效

  • 界面节点如下

    界面节点

  • ClickAnim.js 不多解释,代码有详细的注释

cc.Class({
    extends: cc.Component,

    properties: {

    },
    //使用对象池动态实例化预制资源
    newClickNode(position, callBack) {
        let newNode = null;
        if (!this._clickPool) {

            //初始化对象池
            this._clickPool = new cc.NodePool();
        }
        if (this._clickPool.size() > 0) {

            //从对象池请求对象
            newNode = this._clickPool.get();
            this.setClickNode(newNode, position, callBack);
        } else {

            // 如果没有空闲对象,我们就用 cc.instantiate 重新创建
            cc.loader.loadRes("prefab/clickAnim", cc.Prefab, function (err, prefab) {
                if (err) {
                    return;
                }
                newNode = cc.instantiate(prefab);
                this.setClickNode(newNode, position, callBack);
            }.bind(this));
        }

    },

    setClickNode(newNode, position, callBack) {
        newNode.name = "clickNode"; //设置节点名称
        newNode.setPosition(position);
        newNode.getComponent(cc.Animation).play('click', 0);//播放帧动画
        newNode.setPosition(position); //设置节点位置
        this.clickNode.addChild(newNode); //将新的节点添加到当前组件所有节点上
        if (callBack) {
            callBack(newNode); //回调节点
        }
    },


    start() {
        this._initNodeTouchEvent();
        this.clickNode = this.node.getChildByName("ClickNode");
    },
    _initNodeTouchEvent() {
        //监听事件
        this.node.on(cc.Node.EventType.TOUCH_START, this._onTouchBegin, this);
        this.node.on(cc.Node.EventType.TOUCH_MOVE, this._onTouchMoved, this);
        this.node.on(cc.Node.EventType.TOUCH_END, this._onTouchEnd, this);
        this.node.on(cc.Node.EventType.TOUCH_CANCEL, this._onTouchCancel, this);
    },

    _destroyTouchEvent() {
        //销毁事件
        this.node.off(cc.Node.EventType.TOUCH_START, this._onTouchBegin, this);
        this.node.off(cc.Node.EventType.TOUCH_MOVE, this._onTouchMoved, this);
        this.node.off(cc.Node.EventType.TOUCH_END, this._onTouchEnd, this);
        this.node.off(cc.Node.EventType.TOUCH_CANCEL, this._onTouchCancel, this);
        cc.log("销毁事件...");
    },

    _onTouchBegin: function (event) {
        //获取当前点击的全局坐标
        let temp = event.getLocation();
        //获取当前点击的局部坐标
        let tempClick = this.node.convertToNodeSpaceAR(temp)
        this.newClickNode(tempClick, function (node) {

            if (!node) return

            cc.log("子节点数:" + this.clickNode.children.length);
			//监听帧动画事件
            node.on("clickDone", function (event) {
            	//获取回调中的参数
                event.obj.destroy();
                cc.log("顺利回收....");
            }.bind(this));

        }.bind(this));
    },

    _onTouchMoved: function (event) {
        cc.log('_onTouchMoved');
    },

    _onTouchEnd: function (event) {
        cc.log('_onTouchEnd');
    },

    _onTouchCancel: function (event) {
        cc.log('_onTouchCancel');
    },

    onDestroy() {
        //销毁事件
        this._destroyTouchEvent();
    },
    toBack() {
        cc.director.loadScene("Scene");
    },

    // onLoad () {},
    // update (dt) {},
});

总结

  • 核心实现逻辑:点击屏幕将点击的位置坐标转化为节点空间坐标并动态加载预制资源以及显示帧动画,帧动画播放完时回收节点。
  • 与使用粒子资源实现点击屏幕效果对比,你会发现使用帧动画实现时Draw Call 会比较稳定,推荐使用帧动画来实现

源码地址 Gitee-Brickengine_Guide 欢迎Start :)

到这里就介绍完了,个人能力有限如有错误欢迎指正,如有遗漏欢迎补充。如有疑问欢迎留言亦或者加群「博客左侧栏有群号」一起交流讨论。