加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

cocos2dx-3.2 ClippingNode 遮罩

发布时间:2020-12-14 20:20:04 所属栏目:百科 来源:网络整理
导读:可以根据一个模板切割图片的节点--ClippingNode。这个类提供了一种不规则切割图片的方式,在这种方式以前,我们可以使用纹理类 自带的setTextureRect函数来切割矩形区域,而新特性中提供的ClippingNode最大的不同之处就是裁减将不仅仅局限于矩形,可以根据

可以根据一个模板切割图片的节点--ClippingNode。这个类提供了一种不规则切割图片的方式,在这种方式以前,我们可以使用纹理类

自带的setTextureRect函数来切割矩形区域,而新特性中提供的ClippingNode最大的不同之处就是裁减将不仅仅局限于矩形,可以根据

任何形状进行裁减,而你要做的只是给一个“裁减模板”,首先来看这个类的常用函数(需要说明的是,这里介绍的函数只是这个类独

有的,这个类继承自Node节点类,因此节点类有的函数也就不做介绍了)


下面来看看源码及其API:

    /** 
    ClippingNode 是一个Node的子类,他使用"裁减模板"stencil(漏字模板,我喜欢这样理解) 
     
    去遮挡他的内容(childs)。"裁减模板"stencil也是一个node结点,不会被draw。 
     
    怎么产生效果了?裁剪是通过设置"裁减模板"stencil的alpha值来镂空其中的一些区域。 
     
    作为节点,它就可以用作容器,承载其他节点和精灵。我把它叫底板。 
     
    如果想要对一个节点进行裁剪,那需要给出裁剪的部分,这个裁剪区域,我把它叫模版。 
     
    CCClipingNode裁剪节点在组成上=底板+模版,而在显示上=底板-模版。 
     
    **/  
      
    class CC_DLL ClippingNode : public Node  
    {  
    public:  
        //创建一个没有stencil的裁剪node  
        static ClippingNode* create();  
          
        //创建一个带有stencil的裁剪node,并且些stencil会被自动retain  
        static ClippingNode* create(Node *stencil);  
      
        /** The Node to use as a stencil to do the clipping. 
         The stencil node will be retained. 
         This default to nil. 
         */  
        Node* getStencil() const;  
        void setStencil(Node *stencil);  
          
        //底板内容被裁剪只有设置alpha的值小于stencil模板的值,那么stencil区域就会裁剪掉,  
        //所以如果我们设置clipper的alpha小于1,去裁剪底板。  
        GLfloat getAlphaThreshold() const;  
        void setAlphaThreshold(GLfloat alphaThreshold);  
          
        /** 
            这个用来设置显示的部分: 
            1、裁剪掉的部分 
            2、剩余的部分 
            inverted默认是false,那就是显示被裁剪掉的部分,如果设置成true,那就是显示剩余部分。 
        **/  
        bool isInverted() const;  
        void setInverted(bool inverted);  
          
    };  

我列出了部分我们极度需要的函数接口及其注释。


简单的描述一下,使用ClippingNode的流程:

1、创建”裁剪模板“stencil

2、创建裁剪结点ClippingNode(设置他两的位置相同)

3、为裁剪结点ClippingNode设置stencil

4、设置裁剪结点ClippingNode中要放的内容(精灵)

上面的过程如果使用了setAlphaThreshold和setInverted这两函数接口,就会产生不同的效果,这个按自己的需要自己去设置。上面的注

释里面也注明了设置这两个参数后的效果cpp-test中的ClippingNodeTest例子讲了大量的裁剪使用的方法及效果图,后面文章有分析,这

里实现一个类似于“滤镜”显示文字的ClippingNode例子。


例子1:使用精灵当stencil来裁剪LabelTTF

    void HelloWorld::ClipFunc()  
    {  
        Size s = Director::getInstance()->getWinSize();  
      
        //创建裁剪node  
        ClippingNode *clipper = ClippingNode::create();  
        clipper->setAnchorPoint(Vec2(0.5,0.5));  
        clipper->setPosition(Vec2(s.width * 0.5,s.height * 0.5));  
        //不显示底板  
        //clipper->setInverted(true);  
        //设置alpha值  
        clipper->setAlphaThreshold(0.05);  
      
        //创建一个四边角形当content1  
        DrawNode *sp = DrawNode::create();  
        static Vec2 triangle[4];  
        triangle[0] = Vec2(-120,-120);  
        triangle[1] = Vec2(120,-120);  
        triangle[2] = Vec2(120,120);  
        triangle[3] = Vec2(-120,120);  
        Color4F mask(0,1,0.5);  
        sp->drawPolygon(triangle,4,mask,Color4F(1,1));  
        sp->setPosition(Vec2(50,50));  
        //addChild  
        clipper->addChild(sp);  
      
        //在添加一段文字当content2  
        LabelTTF *tf = LabelTTF::create("Testing long text","Thonburi",35);  
        tf->setPosition(Vec2(50,50));  
        //addChild  
        clipper->addChild(tf);  
      
        //用精灵当stencil  
        Sprite *stencil = Sprite::create("bang.png");  
        stencil->setPosition(Vec2(50,50));  
        stencil->runAction(MoveBy::create(0.5,Vec2(60,0)));  
        MoveBy *moveby = MoveBy::create(1,Vec2(-120,0));  
        DelayTime *delay = DelayTime::create(0.5);  
        stencil->runAction(delay);  
        stencil->runAction(RepeatForever::create(Sequence::create(moveby,moveby->reverse(),NULL)));  
        //设置模板  
        clipper->setStencil(stencil);  
      
        this->addChild(clipper);  
    }  
效果图: 例子2:使用DrawNode当stencil来裁剪精灵
    void HelloWorld::ClipFunc()  
    {  
        //自画一个形状来录stencil  
        DrawNode *stencil = DrawNode::create();  
        static Point triangle[3];  
        triangle[0] = Point(-100,-100);  
        triangle[1] = Point(100,-100);  
        triangle[2] = Point(0,100);  
        Color4F mask(0,1);  
        stencil->drawPolygon(triangle,3,2,1));  
        stencil->setPosition(Point(50,50));  
      
        //裁剪node  
        ClippingNode *clipper = ClippingNode::create();  
        clipper->setAnchorPoint(Point(0.5,0.5));  
        clipper->setPosition(Point(s.width * 0.5,s.height * 0.5));  
        clipper->setAlphaThreshold(0.05);  
        //clipper->setInverted(true);  
        clipper->setStencil(stencil);  
        this->addChild(clipper);  
      
        //加普通对象进裁剪node,让stencil去裁剪  
        Sprite *sp = Sprite::create("bang.png");  
        sp->setPosition(Point(50,50));  
        sp->runAction(MoveBy::create(0.5,Point(60,Point(-120,0));  
        DelayTime *delay = DelayTime::create(0.5);  
        sp->runAction(delay);  
        sp->runAction(RepeatForever::create(Sequence::create(moveby,NULL)));  
        clipper->addChild(sp);  
      
        //加普通对象进裁剪node,让stencil去裁剪  
        LabelTTF *tf = LabelTTF::create("Testing long text",35);  
        tf->setPosition(Point(50,50));  
        clipper->addChild(tf);  
    }  

效果图:


可以发现使用不同的stencil产生的效果决然不同,使用Shape(也就是自己DrawNode的形状时),不要设置alpha的值,要不然就什么也不显示的。


有人留言说使用DrawNode当stencil时,形状为圆形时,实际效果是正方形,原因估计是使用了DrawNode中的drawDot来画的圆形吧?

DrawNode在3.x后不直接提供画空心圆的接口了,那么我们想要一个空心圆怎么办,可以使用多边形逼近,但是锯齿很明显,没研究怎么去消除。

下面是使用空心圆作stencil来ClippingNode的效果图,一切正常:

    /*使用DrawNode画圆当stencil*/  
    void HelloWorld::ClipFunc()  
    {  
        auto s = Director::getInstance()->getWinSize();  
      
        //自画一个形状来录stencil  
        DrawNode *stencil = DrawNode::create();  
        stencil->setAnchorPoint(Point(0.5,0.5));  
        //多边形定点个数;  
        Vec2 points[720];  
        //圆心,相对坐标;  
        Vec2 center(0,0);  
        //半径;  
        float R = 30;  
        /**普及下求圆坐标的方法 
        * 已经半径r、圆心坐标(cX,cY)、圆心偏移角度a,求出其相应偏移角度的坐标(X1,Y1); 
        * X1 = cX + cos(a*3.14/180)*r; 
        * Y1 = cY + sin(a*3.14/180)*r; 
        */  
        // 画空心圆->使用多边形画,分成720等分;  
        // 锯齿蛮明显,不知道怎么消除锯齿;  
        for( int i=0; i < 720; i++)  
        {  
            float x = center.x + cos(0.5*i*3.14/180) * R;  
            float y = center.y + sin(0.5*i*3.14/180) * R;  
            points[i] = Vec2(x,y);  
            log("%f,%f",x,y);  
        }  
        //画多边形;  
        stencil->drawPolygon(points,sizeof(points)/sizeof(points[0]),Color4F(0,0),s.height * 0.5));  
        //clipper->setAlphaThreshold(0.05);  
        //clipper->setInverted(true);  
        clipper->setStencil(stencil);  
        this->addChild(clipper);  
      
        //加普通对象进裁剪node,让stencil去裁剪  
        Sprite *sp = Sprite::create("grossini.png");  
        //sp->setScale(4);  
        sp->setPosition(Point(50,NULL)));  
        clipper->addChild(sp);  
      
        //加普通对象进裁剪node,让stencil去裁剪  
        /*LabelTTF *tf = LabelTTF::create("Testing long text",35); 
        tf->setPosition(Point(50,50)); 
        clipper->addChild(tf);*/  
    }  

效果图:

转自:http://blog.csdn.net/ac_huang/article/details/39554967

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读