如图:
实现思路:
2.在遮罩添加解说UI及相应动画
如图:
具体实现:
为了实现遮罩功能,我们选择一个模板切割图片的节点-- CCClipingNode.它的继承关系如下:
- 首先它是一个节点,继承于CCNode,所以它可以像普通节点一样放入CCLayer,CCScene,CCNode中。
- 作为节点,它就可以用作容器,承载其他节点和精灵。我把它叫底板。
- 如果想要对一个节点进行裁剪,那需要给出裁剪的部分,这个裁剪区域,我把它叫模版。
所以CCClipingNode裁剪节点在组成上=底板+模版,而在显示上=底板+模版.
如图:
2. CCClipingNode API:
注:
getStencil:返回一个节点对象,这个对象就是之前提到的“裁减模板”。
setStencil:设置“裁减模板”。
getAlphaThreshold::这种裁减是可以改变裁减的透明度的,修改这个透明度就是通过设置这个阈值。
setAlphaThreshold:获得这个透明度阈值。
isInverted:之前说过的剪刀剪形状的例子,剪完形状以后,是显示被剪掉的部分,还是显示剩余的部分呢,默认isInverted值是false,是显示被剪掉的部分,设置为true则是显示剩余的部分。这个函数获得这个值。
setInverted:设置isInverted值。
3.CCDrawNode
为了绘制相应图形,使用CCDrawNode类,它的继承关系如下:
4. CCDrawNodeAPI:
注释:
drawDot:绘制点,参数给出坐标位置。
drawSegment:绘制片断,给出起始点,结束点,半径等参数。
drawPolygon:绘制矩形,可以分别给出填充颜色和边框颜色,还可以设置边框宽度。
实现代码:
1)绘制矩形区域:
RectangleLayer.h
- #ifndef __RECTANGLELAYER_LAYER__
- #define __RECTANGLELAYER_LAYER__
- #include "cocos2d.h"
- USING_NS_CC;
- class RectangleLayer:public cocos2d::CCLayer
- {
- public:
- static RectangleLayer* create(const char *pszFileName,CCPoint pos,CCRect rect, int pType);
- virtual bool initWithFile(const char *pszFilename,CCPoint pos,CCRect rect, int pType);
- virtual bool init();
- RectangleLayer(void);
- virtual ~RectangleLayer(void);
- virtual void registerWithTouchDispatcher();
- void refreshRect(CCPoint pos,CCRect rect, int pType);
- bool ccTouchBegan( CCTouch* pTouch, CCEvent* pEvent );
- CCString* getGuideMsgByType(int pType);
- void setGuideVisible(bool isVisible);
- CREATE_FUNC(RectangleLayer);
- private:
- CCSprite* mCircle;
- CCSprite* pHand;
- CCDrawNode *mStencil;
- CCRect m_obRect;
- CCDictionary* m_pMsgDictionary;
- };
- #endif
- #include "RectangleLayer.h"
- USING_NS_CC;
- RectangleLayer::RectangleLayer()
- {
- }
- RectangleLayer::~RectangleLayer()
- {
- }
- RectangleLayer* RectangleLayer::create(const char *pszFileName,CCPoint pos,CCRect rect, int pType)
- {
- RectangleLayer *pobGuideLayer = new RectangleLayer();
- if (pobGuideLayer && pobGuideLayer->initWithFile(pszFileName,pos,rect,pType))
- {
- pobGuideLayer->autorelease();
- return pobGuideLayer;
- }
- CC_SAFE_DELETE(pobGuideLayer);
- return NULL;
- }
- bool RectangleLayer::init()
- {
- if (!CCLayer::init())
- {
- return false;
- }
- return true;
- }
- bool RectangleLayer::initWithFile(const char *pszFileName,CCPoint pos,CCRect rect, int pType)
- {
- if (!CCLayer::init())
- {
- return false;
- }
- m_obRect = rect;
- setTouchEnabled(true);
- //创建cliper对象
- CCClippingNode* pClip = CCClippingNode::create();
- pClip->setInverted(true);
- addChild(pClip);
- mCircle=CCSprite::create(pszFileName);
- mCircle->setPosition(pos);
- mCircle->setAnchorPoint(ccp(-0.5f,0.5f));
- mCircle->runAction(CCRepeatForever::create(CCSequence::createWithTwoActions(CCScaleBy::create(0.05f, 0.95f),
- CCScaleTo::create(0.125f, 1))));
- addChild(mCircle);
- //加入灰色的底板
- CCLayerColor* pColor = CCLayerColor::create(ccc4(0,0,0,180));
- pClip->addChild(pColor);
- mStencil = CCDrawNode::create();
- static ccColor4F green = {0,1,0,1};
- float width = m_obRect.size.width;
- float height = m_obRect.size.height;
- float x = pos.x;
- float y = pos.y;
- static CCPoint rect1[4] = {ccp(0,height),ccp(width,height),ccp(width,0),ccp(0,0)};
- mStencil->drawPolygon(rect1,4,green,0,green);
- mStencil->setPosition(pos);
- pClip->setStencil(mStencil);
- mStencil->runAction(CCRepeatForever::create(CCSequence::createWithTwoActions(CCScaleBy::create(0.05f, 0.95f),
- CCScaleTo::create(0.125f, 1))));
- return true;
- }
- void RectangleLayer::registerWithTouchDispatcher()
- {
- //使用-128和CCMenu优先级相同,并且吞掉事件true//
- CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, -130, true);
- CCLayer::registerWithTouchDispatcher();
- }
- void RectangleLayer::refreshRect(CCPoint pos,CCRect rect, int pType)
- {
- float fRadius=mCircle->getContentSize().width;
- float scale = rect.size.width/fRadius;
- mCircle->setScale(scale);
- mCircle->setPosition(pos);
- mStencil->setPosition(pos);
- mStencil->setScale(scale);
- //设置触碰区域
- float x = pos.x;
- float y = pos.y;
- float width = mCircle->getContentSize().width *scale;
- float height = mCircle->getContentSize().height * scale;
- m_obRect = CCRectMake(x, y, width, height);
- }
- bool RectangleLayer::ccTouchBegan( CCTouch* pTouch, CCEvent* pEvent )
- {
- //得到触摸位置
- CCPoint touchPoint = pTouch->getLocation();
- //判断点是否在矩形 CCRect m_obRect1 = m_obRect中
- if (m_obRect.containsPoint(touchPoint))
- {
- //CCPoint pos = ccp(m_obRect.getMidX(),m_obRect.getMidY());
- CCPoint pos = pTouch->getLocation();
- //这里要转化为UI坐标系(左上角为0,0点)
- pos = CCDirector::sharedDirector()->convertToUI(pos);
- //设置触摸信息
- pTouch->setTouchInfo(pTouch->getID(),pos.x,pos.y);
- CCLog("helloWorld");
- //removeFromParent(); //触发后移除
- return false;
- }
- return true;
- }
- //是否显示
- void RectangleLayer::setGuideVisible(bool isVisible)
- {
- this->setVisible(isVisible);
- setTouchEnabled(isVisible);
- }
- //获取文字信息
- CCString* RectangleLayer::getGuideMsgByType(int pType)
- {
- char typeStr[10];
- sprintf(typeStr, "%d", pType);
- CCString* msg = (CCString*)m_pMsgDictionary->objectForKey(typeStr);
- return msg;
- }
- CCRect m_obRect=CCRectMake(
- 100,
- 160,
- 100,
- 100);
- CCPoint dstPoint = mCircle->getPosition();
- CCPoint newPoint = ccp(100,160);
- RectangleLayer *myGuideLayer = RectangleLayer::create("hand.png",newPoint,m_obRect,0);
- //myGuideLayer->refreshRect(newPoint1,m_obRect1, 0);
- addChild(myGuideLayer);
2)绘制圆形区域:
因实现原理和以上类似,只需要更改下代码即可:
RoundnessLayer.cpp
- #include "RoundnessLayer.h"
- USING_NS_CC;
- RoundnessLayer::RoundnessLayer()
- {
- }
- RoundnessLayer::~RoundnessLayer()
- {
- }
- RoundnessLayer* RoundnessLayer::create(const char *pszFileName,CCPoint pos,CCRect rect, int pType)
- {
- RoundnessLayer *pobGuideLayer = new RoundnessLayer();
- if (pobGuideLayer && pobGuideLayer->initWithFile(pszFileName,pos,rect,pType))
- {
- pobGuideLayer->autorelease();
- return pobGuideLayer;
- }
- CC_SAFE_DELETE(pobGuideLayer);
- return NULL;
- }
- bool RoundnessLayer::init()
- {
- if (!CCLayer::init())
- {
- return false;
- }
- return true;
- }
- bool RoundnessLayer::initWithFile(const char *pszFileName,CCPoint pos,CCRect rect, int pType)
- {
- if (!CCLayer::init())
- {
- return false;
- }
- m_obRect = rect;
- setTouchEnabled(true);
- CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
- //创建裁减节点类
- CCClippingNode* pClip = CCClippingNode::create();
- pClip->setInverted(true);
- addChild(pClip);
- //遮罩层
- CCLayerColor* pColor = CCLayerColor::create(ccc4(0,0,0,180));
- pClip->addChild(pColor);
- mCircle=CCSprite::create(pszFileName);
- float fRadius = rect.size.width/2; //圆的半径
- mCircle->setPosition(pos);
- mCircle->setAnchorPoint(ccp(-0.5f,0.5f));
- mCircle->runAction(CCRepeatForever::create(CCSequence::createWithTwoActions(CCScaleBy::create(0.05f, 0.95f),
- CCScaleTo::create(0.125f, 1))));
- addChild(mCircle);
- //绘制圆形区域
- static ccColor4F green = {1, 1, 1, 1}; //顶点颜色,这里我们没有实质上没有绘制,所以看不出颜色
- const int nCount=100; //圆形其实可以看做正多边形,我们这里用正100边型来模拟园
- const float coef = 2.0f * (float)M_PI/nCount; //计算每两个相邻顶点与中心的夹角
- static CCPoint circle[nCount]; //顶点数组
- for(unsigned int i = 0;i <nCount; i++) {
- float rads = i*coef; //弧度
- circle[i].x = fRadius * cosf(rads); //对应顶点的x
- circle[i].y = fRadius * sinf(rads); //对应顶点的y
- }
- //绘制矩形,可以分别给出填充颜色和边框颜色,还可以设置边框宽度
- mStencil=CCDrawNode::create();
- mStencil->drawPolygon(circle, nCount, green, 0, green); //绘制这个多边形!
- //动起来
- mStencil->runAction(CCRepeatForever::create(CCSequence::createWithTwoActions(CCScaleBy::create(0.05f, 0.95f),
- CCScaleTo::create(0.125f, 1))));
- float x = pos.x + rect.size.width/2;
- float y = pos.y + rect.size.width/2;
- mStencil->setPosition(ccp(x,y));
- //设这模板
- pClip->setStencil(mStencil);
- //CCLayerColor* layer1 = CCLayerColor::create(ccc4(192, 0, 0, 25), rect.size.width, rect.size.height);
- //layer1->setPosition(pos);
- //addChild(layer1);
- return true;
- }
- void RoundnessLayer::registerWithTouchDispatcher()
- {
- //使用-128和CCMenu优先级相同,并且吞掉事件true//
- CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, -130, true);
- CCLayer::registerWithTouchDispatcher();
- }
- void RoundnessLayer::refreshRect(CCPoint pos,CCRect rect, int pType)
- {
- //调整大小
- float fRadius=mCircle->getContentSize().width*0.5;
- float scale = rect.size.width/fRadius;
- //调整光亮区坐标
- float x = pos.x + rect.size.width/2;
- float y = pos.y + rect.size.width/2;
- mCircle->setScale(scale);
- mCircle->setPosition(pos);
- mStencil->setPosition(ccp(x, y));
- mStencil->setScale(scale);
- //设置触碰区域
- float rectX = pos.x;
- float rectY = pos.y;
- float width = mCircle->getContentSize().width *scale;
- float height = mCircle->getContentSize().height * scale;
- m_obRect = CCRectMake(rectX, rectY, width, height);
- }
- bool RoundnessLayer::ccTouchBegan( CCTouch* pTouch, CCEvent* pEvent )
- {
- //得到触摸位置
- CCPoint touchPoint = pTouch->getLocation();
- //判断点是否在矩形 CCRect m_obRect1 = m_obRect中
- if (m_obRect.containsPoint(touchPoint))
- {
- CCPoint pos = ccp(m_obRect.getMidX(),m_obRect.getMidY());
- //这里要转化为UI坐标系(左上角为0,0点)
- pos = CCDirector::sharedDirector()->convertToUI(pos);
- //设置触摸信息
- pTouch->setTouchInfo(pTouch->getID(),pos.x,pos.y);
- CCLog("helloWorld");
- return false;
- }
- CCLog("no");
- return true;
- }
- void RoundnessLayer::setGuideVisible(bool isVisible)
- {
- this->setVisible(isVisible);
- setTouchEnabled(isVisible);
- }
- CCString* RoundnessLayer::getGuideMsgByType(int pType)
- {
- char typeStr[10];
- sprintf(typeStr, "%d", pType);
- CCString* msg = (CCString*)m_pMsgDictionary->objectForKey(typeStr);
- return msg;
- }
有关解说UI及动画的话,就按自己的项目要求贴到遮罩层上,就OK了。
若想让真机正常显示,稍微更改接口参数:
for iOS: in AppController replace the gl-view creation with:
- EAGLView *__glView = [EAGLView viewWithFrame: [window bounds]
- pixelFormat: kEAGLColorFormatRGBA8
- depthFormat: GL_DEPTH24_STENCIL8_OES
- preserveBackbuffer: NO
- sharegroup: nil
- multiSampling: NO
- numberOfSamples: 0];
for Android: in game activity:
- public Cocos2dxGLSurfaceView onCreateView() {
- Cocos2dxGLSurfaceView glSurfaceView = new Cocos2dxGLSurfaceView(this);
- glSurfaceView.setEGLConfigChooser(5, 6, 5, 0, 16, 8);
- return glSurfaceView;
- }
引用博客:
http://bbs.9ria.com/thread-182383-1-1.html
http://blog.csdn.net/jackystudio/article/details/17160973