如何在cocos create中实现刮刮卡效果

这篇文章简单介绍下如何在cocos create里面实现刮刮卡的效果。
首先看该节点的结构目录
在这里插入图片描述
ScrapeArea为主节点,控制这个组件的代码防在这个节点上面。这个节点要注意的事项就是本节点的size数值一点要大于texture节点,才能擦除操作。因为这个要完的点击、触摸等相应的事件。
mask为反向遮罩节点,必须确保大小和位置为(0,0)。
在这里插入图片描述

这是实现擦除效果的关键,运用到的就是反向遮罩已经画先这两个功能。 首先为mask节点添加mask组件,记得将Inverted(即反向遮罩勾上)。
在这里插入图片描述
遮罩的含义是在含有mask组件的节点(下面简称mask节点)的子节点中,子节点超出mask范围(即size)的部分不给予显示。反向遮罩的功能正好想反,是子节点在mask节点范围内的部分不给予显示。这正式本方法实现擦除效果的原来,通过绘图,改变mask节点的大小,进而反向遮挡texture节点,露出原本的图片。

textrue为图片节点,就是过一个将要被刮开的图片。

我们来看一下具体代码的实现过程吧
代码里graphics的属性,可以参考cocos的API文档。

cc.Class({
    extends: cc.Component,
    properties: {
        mask: {
            default: null,
            type: cc.Mask,
            tooltip:'需要刮开的'
        },
    },

    // 激活主节点的监听事件
    onLoad: function () {
        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);
    },

    /**
     * 结束刮图的动作监听
     */
    endScrape(){
        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);
    },
    /**
     * 点击开始
     * @param {*} event 
     */
    _onTouchBegin: function (event) {
        cc.log('touchBegin');    
        this.comFun(event);
    },

    _onTouchMoved: function (event) {
        this.comFun(event);
    },

    _onTouchEnd: function (event) {
        cc.log('touchEnd');
        this.checkScrape();
        this.comFun(event);
    },

    _onTouchCancel: function (event) {
        cc.log('TouchCancel')
        this.checkScrape();
    },
    
    onDestroy: function () {
        this.endScrape();
    },

    /**
     * 获得点击的位置
     * @param {事件} e 
     */
    getPos(e) {
        var point = e.touch.getLocation();
        point = this.node.convertToNodeSpaceAR(point);
        return point;
    },

    comFun(event) {
        var point = this.getPos(event);
        this.checkPixelPiont(point);
        this._addCircle(point);
    },

    /**
     * 进行刮开的操作
     * @param {*} point 
     */
    _addCircle: function (point) {
        var graphics = this.mask._graphics;
        //cc.log("xxxx:",graphics)
        var color = cc.color(0, 0, 0, 255);
        // 绘制椭圆
        graphics.ellipse(point.x, point.y, 60, 60);
        graphics.lineWidth = 2;
        // 填充颜色为透明
        graphics.fillColor = color;
        // 开始填充颜色
        graphics.fill();
    },   
});

然后将代码拖的主节点上,将mask放入槽中,刮刮卡的基本的功能就实现了。
在这里插入图片描述

下面是完整版刮刮卡代码的介绍,增加当擦除到70%的时候所有texture消失,执行回调事件。

本方法是先根据接触点的大小在图片上排列一个点矩阵,每个点矩阵有一个检测范围且只能被检测一次,没次被检测刮开的数都会执行++操作,知道接触点等于目标点(刮开的范围可以自己设置)后,遮罩的图片消失,并执行回调函数。
注:改方法不用设置主节点ScrapeArea节点的大小,在代码会改变它的大小的。

cc.Class({
    extends: cc.Component,

    properties: {
        mask: {
            default: null,
            type: cc.Mask,
            tooltip:'需要刮开的'
        },
        scrapteRadiusX: {
            default: 25.0,
            type: cc.Float,
            tooltip: '绘制点图形的x轴半径'
        },
        scrapteRadiusY: {
            default: 35.0,
            type: cc.Float,
            tooltip: '绘制点图形的Y轴半径'
        },
        scrapteArea: {
            default: 0.5,
            type: cc.Float,
            tooltip: '需要刮开的图层面积的多少'
        },
        scrapeEvents: {
            default: [],
            type: [cc.Component.EventHandler],
            tooltip: '擦除完成后所触发的事件'
        },

    },

    onLoad: function () {
        this.activeMaskNode();
    },

    activeMaskNode() {
        this.getinitNum();
        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);
    },

    /**
     * 结束刮图的动作监听
     */
    endScrape(){
        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);
    },
    /**
     * 点击开始
     * @param {*} event 
     */
    _onTouchBegin: function (event) {
        cc.log('touchBegin');    
        this.comFun(event);
    },

    _onTouchMoved: function (event) {
        this.comFun(event);
    },

    _onTouchEnd: function (event) {
        cc.log('touchEnd');
        this.checkScrape();
        this.comFun(event);
    },

    _onTouchCancel: function (event) {
        cc.log('TouchCancel')
        this.checkScrape();
    },
    
    onDestroy: function () {
        this.endScrape();
    },

    comFun(event) {
        var point = this.getPos(event);
        this.checkPixelPiont(point);
        this._addCircle(point);
    },

    /**
     * 进行刮开的操作
     * @param {*} point 
     */
    _addCircle: function (point) {
        var graphics = this.mask._graphics;
        //cc.log("xxxx:",graphics)
        var color = cc.color(0, 0, 0, 255);
        // 绘制椭圆
        graphics.ellipse(point.x, point.y, this.scrapteRadiusX * 2, this.scrapteRadiusY * 2);
        graphics.lineWidth = 2;
        // 填充颜色为透明
        graphics.fillColor = color;
        // 开始填充颜色
        graphics.fill();
    },

    /**
     * 检查是否完成擦除
     */
    checkScrape() {
        cc.log('目标数是:' + this.achieveNum);
        cc.log('现在已经刮开' + this.pixelNum);
        if (this.achieveNum < this.pixelNum) {
            cc.log("已经刮完图层");
            this.achieveScrape();
        }
    },

    /**
     * 获得点击的位置
     * @param {事件} e 
     */
    getPos(e) {
        var point = e.touch.getLocation();
        point = this.node.convertToNodeSpaceAR(point);
        return point;
    },

    /**
     * 获取初始值
     */
    getinitNum() {
        this.pixelNum = 0;
        // 记录要擦除多少像素点才能完成擦除操作
        this.achieveNum = this.scrapteArea * this.initPixel();
    },

    /**
     * 根据所设计的接触点的大小设置出一个点矩阵,在根据接触点与点矩阵的
     * 距离判断当前已经刮开了图像的多少了
     */
    initPixel() {
        this.scrapeNode = this.mask.node.children[0];
        var x = this.scrapeNode.width, y = this.scrapeNode.height;

        //根据所设texture的大小来改变主节点的大小
        this.node.width = x;
        this.node.height = y;

        //根据接触点的大小来设置矩阵点多少以及点之间的距离
        this.widthWide = x / 2 + 20;
        this.heightWide = x / 2 + 20;
        var zx = x / 2, zy = y / 2, dx = -zx, dy = -zy, dy1 = dy;
        var pixelPiont = [];
        var rx = this.scrapteRadiusX * 2;
        var ry = this.scrapteRadiusY * 2;

        // 开始排列矩阵
        for (; dx <= zx; dx += rx) {
            for (dy = dy1; dy <= zy; dy += ry) {
                var p = [dx, dy];
                // 该属性确保每个矩阵点只能有一次的检测操作
                // 被检测完后变为false不能被二次检测
                p.isTouch = true;
                pixelPiont.push(p);
            }
        }
        this.pixelPiont = pixelPiont;
        //返回像素点的个数
        return pixelPiont.length;
    },

    /**
     * 检查是否画在新的像素点上,若是话在了新的点上,接使刮开数执行++操作
     */
    checkPixelPiont(point) {
        var pixelPiont = this.pixelPiont;
        var x, y;
        for (var i in pixelPiont) {
            x = Math.abs(point.x - pixelPiont[i][0]);
            y = Math.abs(point.y - pixelPiont[i][1]);
            if (x <= this.scrapteRadiusX && y <= this.scrapteRadiusY && pixelPiont[i].isTouch) {
                // 让该元素不可以响应触摸功能
                pixelPiont[i].isTouch = false;
                this.pixelNum++;
                return;
            }
        }
    },

    /**
     * 完成刮蹭事件
     */
    achieveScrape() {
        this.endScrape();
        // 执行渐隐效果,卡片消失
        this.node.runAction(cc.fadeOut(0.5));
        this.scheduleOnce((() => {
            // 执行回调事件
            cc.Component.EventHandler.emitEvents(this.scrapeEvents, new cc.Event.EventCustom('scrapeEvents'));
            //this.node.destroy();
        }).bind(this), 0.6);
    },
});

猜你喜欢

转载自blog.csdn.net/qq_43788640/article/details/88748041