2016年5月11日下午2:14
一.基本定义
ClippingNode(裁剪节点)可以用来对节点进行裁剪,可以根据一个模板切割图片的节点,生成任何形状的节点显示。ClippingNode是利用模板遮罩来完成对Node区域裁剪的技术。
原理图:
二.上手实例
游戏中,新手引导算是一个比较重要的部分,指引玩家一步步了解游戏,深入游戏,作用相当于老司机啊,告诉我们正确的打开方式。
引导的实现一般分为两步:
- 把背景置灰,把要操作的区域高亮。
- 屏蔽所有的触摸,只能触摸高亮区域。
下面拿我们游戏中的代码做一下演示:
//-------------------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,150)) clipNode.addChild(that.layerBg) clipNode.setInverted(true)//设置底板可见 //创建模板 var sentcil = new cc.LayerColor(cc.color(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,}) 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的像素不被绘制,只绘制了一个小圆。