zoukankan      html  css  js  c++  java
  • cocos2dx-js——clippingNode使用

    一.基本定义


    ClippingNode(裁剪节点)可以用来对节点进行裁剪,可以根据一个模板切割图片的节点,生成任何形状的节点显示。ClippingNode是利用模板遮罩来完成对Node区域裁剪的技术。 

    原理图: 
    这里写图片描述

    二.上手实例


    游戏中,新手引导算是一个比较重要的部分,指引玩家一步步了解游戏,深入游戏,作用相当于老司机啊,告诉我们正确的打开方式。 
    引导的实现一般分为两步:

    1. 把背景置灰,把要操作的区域高亮。 
    2. 屏蔽所有的触摸,只能触摸高亮区域。

    下面拿我们游戏中的代码做一下演示:

            //-------------------1.只显示高亮区域-------------------//
    
            //获取需要高亮的控件
            that.rootNode = ccs.load("res/ArenaMain.json").node;
            that.addChild(that.rootNode);
            var btn_change = that.seekWidgetByName(that.rootNode,"btn_change")
            that.widget = btn_change
    
            //创建裁剪节点
            var clipNode = new cc.ClippingNode()
            that.addChild(clipNode)
    
            //创建底板,将屏幕遮灰
            that.layerBg = new cc.LayerColor(cc.color(0, 0, 0, 150))
            clipNode.addChild(that.layerBg)
            clipNode.setInverted(true)//设置底板可见
    
            //创建模板
            var sentcil = new cc.LayerColor(cc.color(255, 255, 255, 100))
            clipNode.setStencil(sentcil)//设置裁剪模板
            var worldPosition = btn_change.getParent().convertToWorldSpace(btn_change.getPosition())
            sentcil.setPosition(worldPosition)
            sentcil.ignoreAnchorPointForPosition(btn_change.isIgnoreAnchorPointForPosition())
            sentcil.setContentSize(btn_change.getContentSize())
            sentcil.setAnchorPoint(btn_change.getAnchorPoint())
    
            //-------------------------------------------------------//
    

    效果图: 

    这里写图片描述

        //-------------------2.只能触摸高亮区域-------------------//
        var listener = cc.EventListener.create({
            event: cc.EventListener.TOUCH_ONE_BY_ONE,
            swallowTouches: true,
            onTouchBegan: function (touch, event) {
                if(that.widget){
                    //如果触摸点位于高亮区域,则可向下传递触摸,否则吞噬掉触摸
                    var isHit = that.widget.hitTest(touch.getLocation())
                    if(isHit){
                        listener.setSwallowTouches(false)
                    }else{
                        listener.setSwallowTouches(true)
                    }
                }
                //cc.log("wade setTouch 111")
                return true;
            },
            onTouchMoved:function (touch, event){},
            onTouchEnded:function (touch, event){
            },
            onTouchCancelled:function (touch, event){
            }
        })
    
        cc.eventManager.addListener(listener, that.layerBg)
    
        //-------------------------------------------------------//
    

    三.深入研究


    1.举例:小球透视

    模板:Node节点,放入4个Sprite的小球 。 
    底板:Node节点,放入1个Sprite的Logo图。 
    背景:一个Sprite的温馨场景图。

    这里写图片描述

    代码实现:

        //创建最底层的温馨场景图
        this.sprite = new cc.Sprite("res/bg1.jpg")
        this.sprite.attr({
            x: cc.winSize.width / 2,
            y: cc.winSize.height / 2,
        })
        this.addChild(this.sprite)
    
        //创建裁剪节点
        var clipNode = new cc.ClippingNode()
        clipNode.attr({
            x: 0,
            y: 0,
            anchorX : 0,
            anchorY : 0,
        })
        this.addChild(clipNode)
        //设置alpha阈值
        clipNode.setAlphaThreshold(0.05)
    
        //创建底板
        var content = new cc.Sprite("res/powered.png")
        content.attr({
            x: cc.winSize.width/2,
            y: cc.winSize.height/2,
            anchorX : 0.5,
            anchorY : 0.5,
        })
        clipNode.addChild(content)
        //底板可见
        clipNode.setInverted(true)
    
    
        //创建模板
        var ball1 = new cc.Sprite("res/SpookyPeas.png")
        var ball2 = new cc.Sprite("res/SpookyPeas.png")
        var ball3 = new cc.Sprite("res/SpookyPeas.png")
        var ball4 = new cc.Sprite("res/SpookyPeas.png")
        ball1.setPosition(cc.winSize.width/2-40,cc.winSize.height/2-40)
        ball2.setPosition(cc.winSize.width/2+40,cc.winSize.height/2-40)
        ball3.setPosition(cc.winSize.width/2-40,cc.winSize.height/2+40)
        ball4.setPosition(cc.winSize.width/2+40,cc.winSize.height/2+40)
    
        var sentcil = new cc.Node()
        sentcil.attr({
            anchorX : 0,
            anchorY : 0,
        })
        sentcil.addChild(ball1)
        sentcil.addChild(ball2)
        sentcil.addChild(ball3)
        sentcil.addChild(ball4)
    
        clipNode.setStencil(sentcil)
    

    效果展示: 
    这里写图片描述

    分析总结:

    通过ClippingNode进行裁剪遮罩,其实是这样的:

    将模板(Stencil)上所有元素的形状集合作为 “形状模板” ,其元素本身不渲染。

    使用“形状模板”对底板进行裁剪。

    显示从底板上裁剪下来的图片区域。

    主要函数:

    倒置显示(Inverted) 
    false :显示被模板裁剪下来的底板内容。默认为false。 
    true :显示剩余部分。

    clipNode.setInverted(false)
    

    这里写图片描述

    alpha阈值(alphaThreshold) 
    alpha:表示像素的透明度值。 
    只有模板(stencil)中像素的alpha值大于alpha阈值时,内容才会被绘制。

    alpha阈值(alphaThreshold) :取值范围 [0,1] 。

    默认为 1 ,表示alpha测试默认关闭,即全部绘制。

    若不是1 ,表示只绘制模板中,alpha像素大于alphaThreshold的内容。

    具体说明:

    以下是一张 40*40 的图片,其中小球以外的其他区域像素为透明的(即: alpha为 0 )。 
    这里写图片描述

    (1)在 不设置AlphaThreshold闸值 , 或者 setAlphaThreshold(1.0f) ,的情况下:

    这里写图片描述

    (2)在 设置setAlphaThreshold(0.5f) ,的情况下:

    这里写图片描述

    结论:

    可以发现在不设置alpha闸值时,模板绘制的区域为一个40*40的矩形。

    设置了alpha闸值为0.5时,透明度alpha为0的像素不被绘制,只绘制了一个小圆。

  • 相关阅读:
    Arm的几种工作模式
    Linux 串口驱动初始化前置定位crash log
    GPS的经纬度格式及转换
    git 常用命令
    windows 下 mongodb studio 3t 破解无限使用脚本
    从头开始 一、第一天
    十九、IDEA的pom文件手动添加依赖
    十八、{ "a", "ab", "ac", "abc", "de", "bc", "e" }不使用Arrays.sort()进行排序
    十七、Java中数组常见的几种排序方法!
    十六、IDEA创建一个maven工程
  • 原文地址:https://www.cnblogs.com/guangyun/p/8391951.html
Copyright © 2011-2022 走看看