cocos2dx-3.2(35) ClippingNode 遮罩

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

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

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

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


下面来看看源码及其API:


[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2. ClippingNode 是一个Node的子类,他使用"裁减模板"stencil(漏字模板,我喜欢这样理解) 
  3.  
  4. 去遮挡他的内容(childs)。"裁减模板"stencil也是一个node结点,不会被draw。 
  5.  
  6. 怎么产生效果了?裁剪是通过设置"裁减模板"stencil的alpha值来镂空其中的一些区域。 
  7.  
  8. 作为节点,它就可以用作容器,承载其他节点和精灵。我把它叫底板。 
  9.  
  10. 如果想要对一个节点进行裁剪,那需要给出裁剪的部分,这个裁剪区域,我把它叫模版。 
  11.  
  12. CCClipingNode裁剪节点在组成上=底板+模版,而在显示上=底板-模版。 
  13.  
  14. **/  
  15.   
  16. class CC_DLL ClippingNode : public Node  
  17. {  
  18. public:  
  19.     //创建一个没有stencil的裁剪node  
  20.     static ClippingNode* create();  
  21.       
  22.     //创建一个带有stencil的裁剪node,并且些stencil会被自动retain  
  23.     static ClippingNode* create(Node *stencil);  
  24.   
  25.     /** The Node to use as a stencil to do the clipping. 
  26.      The stencil node will be retained. 
  27.      This default to nil. 
  28.      */  
  29.     Node* getStencil() const;  
  30.     void setStencil(Node *stencil);  
  31.       
  32.     //底板内容被裁剪只有设置alpha的值小于stencil模板的值,那么stencil区域就会裁剪掉,  
  33.     //所以如果我们设置clipper的alpha小于1,去裁剪底板。  
  34.     GLfloat getAlphaThreshold() const;  
  35.     void setAlphaThreshold(GLfloat alphaThreshold);  
  36.       
  37.     /** 
  38.         这个用来设置显示的部分: 
  39.         1、裁剪掉的部分 
  40.         2、剩余的部分 
  41.         inverted默认是false,那就是显示被裁剪掉的部分,如果设置成true,那就是显示剩余部分。 
  42.     **/  
  43.     bool isInverted() const;  
  44.     void setInverted(bool inverted);  
  45.       
  46. };  

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


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

1、创建”裁剪模板“stencil

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

3、为裁剪结点ClippingNode设置stencil

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

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

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

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


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

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. void HelloWorld::ClipFunc()  
  2. {  
  3.     Size s = Director::getInstance()->getWinSize();  
  4.   
  5.     //创建裁剪node  
  6.     ClippingNode *clipper = ClippingNode::create();  
  7.     clipper->setAnchorPoint(Vec2(0.5,0.5));  
  8.     clipper->setPosition(Vec2(s.width * 0.5, s.height * 0.5));  
  9.     //不显示底板  
  10.     //clipper->setInverted(true);  
  11.     //设置alpha值  
  12.     clipper->setAlphaThreshold(0.05);  
  13.   
  14.     //创建一个四边角形当content1  
  15.     DrawNode *sp = DrawNode::create();  
  16.     static Vec2 triangle[4];  
  17.     triangle[0] = Vec2(-120, -120);  
  18.     triangle[1] = Vec2(120, -120);  
  19.     triangle[2] = Vec2(120, 120);  
  20.     triangle[3] = Vec2(-120,120);  
  21.     Color4F mask(0,1,0,0.5);  
  22.     sp->drawPolygon(triangle, 4, mask, 0, Color4F(1,0,0,1));  
  23.     sp->setPosition(Vec2(50,50));  
  24.     //addChild  
  25.     clipper->addChild(sp);  
  26.   
  27.     //在添加一段文字当content2  
  28.     LabelTTF *tf = LabelTTF::create("Testing long text""Thonburi", 35);  
  29.     tf->setPosition(Vec2(50,50));  
  30.     //addChild  
  31.     clipper->addChild(tf);  
  32.   
  33.     //用精灵当stencil  
  34.     Sprite *stencil = Sprite::create("bang.png");  
  35.     stencil->setPosition(Vec2(50,50));  
  36.     stencil->runAction(MoveBy::create(0.5, Vec2(60,0)));  
  37.     MoveBy *moveby = MoveBy::create(1, Vec2(-120,0));  
  38.     DelayTime *delay = DelayTime::create(0.5);  
  39.     stencil->runAction(delay);  
  40.     stencil->runAction(RepeatForever::create(Sequence::create(moveby, moveby->reverse(), NULL)));  
  41.     //设置模板  
  42.     clipper->setStencil(stencil);  
  43.   
  44.     this->addChild(clipper);  
  45. }  


效果图:



例子2:使用DrawNode当stencil来裁剪精灵

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. void HelloWorld::ClipFunc()  
  2. {  
  3.     //自画一个形状来录stencil  
  4.     DrawNode *stencil = DrawNode::create();  
  5.     static Point triangle[3];  
  6.     triangle[0] = Point(-100, -100);  
  7.     triangle[1] = Point(100, -100);  
  8.     triangle[2] = Point(0, 100);  
  9.     Color4F mask(0,1,0,1);  
  10.     stencil->drawPolygon(triangle, 3, mask, 2, Color4F(1,0,0,1));  
  11.     stencil->setPosition(Point(50,50));  
  12.   
  13.     //裁剪node  
  14.     ClippingNode *clipper = ClippingNode::create();  
  15.     clipper->setAnchorPoint(Point(0.5,0.5));  
  16.     clipper->setPosition(Point(s.width * 0.5, s.height * 0.5));  
  17.     clipper->setAlphaThreshold(0.05);  
  18.     //clipper->setInverted(true);  
  19.     clipper->setStencil(stencil);  
  20.     this->addChild(clipper);  
  21.   
  22.     //加普通对象进裁剪node,让stencil去裁剪  
  23.     Sprite *sp = Sprite::create("bang.png");  
  24.     sp->setPosition(Point(50,50));  
  25.     sp->runAction(MoveBy::create(0.5, Point(60,0)));  
  26.     MoveBy *moveby = MoveBy::create(1, Point(-120,0));  
  27.     DelayTime *delay = DelayTime::create(0.5);  
  28.     sp->runAction(delay);  
  29.     sp->runAction(RepeatForever::create(Sequence::create(moveby, moveby->reverse(), NULL)));  
  30.     clipper->addChild(sp);  
  31.   
  32.     //加普通对象进裁剪node,让stencil去裁剪  
  33.     LabelTTF *tf = LabelTTF::create("Testing long text""Thonburi", 35);  
  34.     tf->setPosition(Point(50,50));  
  35.     clipper->addChild(tf);  
  36. }  

效果图:



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


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

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

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

[cpp]  view plain copy
  1. /*使用DrawNode画圆当stencil*/  
  2. void HelloWorld::ClipFunc()  
  3. {  
  4.     auto s = Director::getInstance()->getWinSize();  
  5.   
  6.     //自画一个形状来录stencil  
  7.     DrawNode *stencil = DrawNode::create();  
  8.     stencil->setAnchorPoint(Point(0.5,0.5));  
  9.     //多边形定点个数;  
  10.     Vec2 points[720];  
  11.     //圆心,相对坐标;  
  12.     Vec2 center(0,0);  
  13.     //半径;  
  14.     float R = 30;  
  15.     /**普及下求圆坐标的方法 
  16.     * 已经半径r、圆心坐标(cX,cY)、圆心偏移角度a,求出其相应偏移角度的坐标(X1,Y1); 
  17.     * X1 = cX + cos(a*3.14/180)*r; 
  18.     * Y1 = cY + sin(a*3.14/180)*r; 
  19.     */  
  20.     // 画空心圆->使用多边形画,分成720等分;  
  21.     // 锯齿蛮明显,不知道怎么消除锯齿;  
  22.     forint i=0; i < 720; i++)  
  23.     {  
  24.         float x = center.x + cos(0.5*i*3.14/180) * R;  
  25.         float y = center.y + sin(0.5*i*3.14/180) * R;  
  26.         points[i] = Vec2(x,y);  
  27.         log("%f,%f", x, y);  
  28.     }  
  29.     //画多边形;  
  30.     stencil->drawPolygon(points, sizeof(points)/sizeof(points[0]), Color4F(0,1,0,0), 1, Color4F(1,0,0,1));  
  31.     stencil->setPosition(Point(50,50));  
  32.   
  33.     //裁剪node  
  34.     ClippingNode *clipper = ClippingNode::create();  
  35.     clipper->setAnchorPoint(Point(0.5,0.5));  
  36.     clipper->setPosition(Point(s.width * 0.5, s.height * 0.5));  
  37.     //clipper->setAlphaThreshold(0.05);  
  38.     //clipper->setInverted(true);  
  39.     clipper->setStencil(stencil);  
  40.     this->addChild(clipper);  
  41.   
  42.     //加普通对象进裁剪node,让stencil去裁剪  
  43.     Sprite *sp = Sprite::create("grossini.png");  
  44.     //sp->setScale(4);  
  45.     sp->setPosition(Point(50,50));  
  46.     sp->runAction(MoveBy::create(0.5, Point(60,0)));  
  47.     MoveBy *moveby = MoveBy::create(1, Point(-120,0));  
  48.     DelayTime *delay = DelayTime::create(0.5);  
  49.     sp->runAction(delay);  
  50.     sp->runAction(RepeatForever::create(Sequence::create(moveby, moveby->reverse(), NULL)));  
  51.     clipper->addChild(sp);  
  52.   
  53.     //加普通对象进裁剪node,让stencil去裁剪  
  54.     /*LabelTTF *tf = LabelTTF::create("Testing long text", "Thonburi", 35); 
  55.     tf->setPosition(Point(50,50)); 
  56.     clipper->addChild(tf);*/  
  57. }  

效果图:



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值