cocos2d-x學習日誌(17) --新手嚮導

    新手引導:爲了讓第一次進入遊戲的玩家能更加輕鬆容易的瞭解遊戲功能。

    如圖:





實現思路:


  1.採用遮罩的形式突出引導重點,同時屏蔽其它功能。

  2.在遮罩添加解說UI及相應動畫


  如圖:




  注:光亮區域即是可觸碰區域。


具體實現:


1.CCClipingNode

  爲了實現遮罩功能,我們選擇一個模板切割圖片的節點-- 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
RectangleLayer.cpp

#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;  
}  
在HelloWorldScene.cpp 的init方法添加代碼:

	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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章