下面我們就詳細講述這幾個要點:
一.畫面的變化.
對個這個不同的遊戲的做法不盡相同,歸結起來大概有這麼幾種:
1.畫面整體變暗
這個比較簡單,cocos2d就有現成接口:
CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize(); //第一個參數是顏色ccc4(r,g,b,a) a取值(0~255),越大越不透明 下面兩個參數為寬高,不傳默認為屏幕大小 CCLayerColor* pLayer=CCLayerColor::create(ccc4(0,0,0,200),visibleSize.width,visibleSize.height); //CCLayerColor* pLayer=CCLayerColor::create(ccc4(0,0,0,200)); addChild(pLayer,100);
效果如下:
然後你可以在這層之上添加精靈,最後的效果可能是這個樣子的:
註:圖片源自網絡,如果有版權問題~你丫去死吧! 請聯繫我!
2.局部高亮
比較簡單的方法是準備幾張張局部高亮的圖片,隨著引導進度變化而切換!優點是可以做的比較精美,缺點是資源量會比較大!另一種方法是在畫面整體變暗的基礎上摳掉部分區域,還好cocos2d提供了CCClippingNode接口(2.1+版)!
CCClippingNode類比較複雜,但我們只用明白兩個東西就好:一個是CCClippingNode的Stencil,一個CCClippingNode的Child,怎麼理解呢?請看下圖:
這個東西相信大家都有印象吧,上面的圖案(鏤空部分)就是 CCClippingNode的Stencil(模板),實體部分就是CCClippingNode的child(底板),是不是很好明白,讓我們用代碼來實現吧:
//創建cliper對象 CCClippingNode* pClip=CCClippingNode::create(); addChild(pClip); //加入灰色的底板 CCLayerColor* pColor=CCLayerColor::create(ccc4(0,0,0,200)); pClip->addChild(pColor);
讓我來加入模板:
//創建drawnode對象 CCDrawNode *m_pAA=CCDrawNode::create(); static ccColor4F green = {0, 1, 0, 1}; static CCPoint rect[4]={ccp(-50,50),ccp(50,50),ccp(50,-50),ccp(-50,-50)}; //用上面的數據保存一個100x100的矩形 m_pAA->drawPolygon(rect, 4, green, 0, green); //設置到屏幕的中心 m_pAA->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y)); //設置為pclip的模板 pClip->setStencil(m_pAA);
CCDrawNode是用來繪製幾何圖形的,drawPolygon使用繪製多邊形,參數為頂點數組,頂點數量,邊框寬度,和填充顏色!這裡要注意一點:千萬不要addChild(m_pAA);因為一旦addchild,m_pAA就會被繪製出來,我們是要用它做剪裁!他會在CCClippingNode內部被使用!
我們會看到這樣的效果:
額,貌似和我們想想的不太一樣啊,為什麼呢?那是因為CCClippingNode有一個選項是是否反向,既顯示Stencil呢還是child減去Stencil的部分!默認為顯示顯示鏤空(Stencil)部分(false),因此我們要改變選項:
//是否反向? pClip->setInverted(true);
效果如下,是不是很棒:
3.組合效果(將2的矩形改成圓,再加上圖片)
讓我們先看這張圖片,是不是很棒?右下角黃色矩形區域是高亮的,在配上圖片說明,很不錯的效果!
讓我們來實現類似的效果吧,用到的資源:
//創建cliper CCClippingNode* pClip=CCClippingNode::create(); pClip->setInverted(true); addChild(pClip); //添加底板 CCLayerColor* pColor=CCLayerColor::create(ccc4(0,0,0,200)); pClip->addChild(pColor); //繪製圓形區域 static ccColor4F green = {0, 1, 0, 1};//頂點顏色,這裡我們沒有實質上沒有繪製,所以看不出顏色 float fRadius=55.0f;//圓的半徑 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 } CCDrawNode *pStencil=CCDrawNode::create(); pStencil->drawPolygon(circle, nCount, green, 0, green);//繪製這個多邊形! //動起來 pStencil->runAction(CCRepeatForever::create(CCSequence::createWithTwoActions(CCScaleBy::create(0.05f, 0.95f), CCScaleTo::create(0.125f, 1)))); pStencil->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y)); //設這模板 pClip->setStencil(pStencil); //添加圓和手的圖片 CCSprite*pCircle=CCSprite::create("circle.png"); pCircle->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y)); pCircle->runAction(CCRepeatForever::create(CCSequence::createWithTwoActions(CCScaleBy::create(0.05f, 0.95f), CCScaleTo::create(0.125f, 1)))); addChild(pCircle); CCSprite* pHand=CCSprite::create("hand.png"); pHand->setAnchorPoint(ccp(0.0f,1.0f)); pHand->setPosition(ccp(pCircle->getContentSize().width/2,pCircle->getContentSize().height/2)); pCircle->addChild(pHand);
上面是全部的代碼,效果圖如下(動態的會更好)沒有加圓圈和手之前和之後:
那麼如何改變高亮區域得位置呢?很簡單,只用改變pStencil的位置即可!可以考慮記為成員變量在ccTouchesBegan中改變位置,這樣就會高亮區域就會跟著你的鼠標走啦!
二.觸摸和按鈕響應
1.開啟觸摸 阻止穿透響應 判斷落點
讓我們繼續看下面的這張圖片:
這張圖片中應該只有右下角的」冒險」按鈕能夠響應的到,在這裡說下思路:
為了讓其他區域的按鈕響應不到,我們應該提高上層(CClayer)的響應優先級為-128和按鈕一樣,這樣的話如果上層(CClayer)後加入遊戲addchild的話,會先收到觸摸消息.
在收到觸摸消息ccTouchBegan時,判斷點擊的地方是否在黃色矩形區域中,在的話return false 交給下層的按鈕去響應,否則return true 阻止消息繼續傳遞.
下面是代碼片段:
1).開啟觸摸
在收到觸摸消息ccTouchBegan時,判斷點擊的地方是否在黃色矩形區域中,在的話return false 交給下層的按鈕去響應,否則return true 阻止消息繼續傳遞.
下面是代碼片段:
1).開啟觸摸
bool CTeachLayer::init() { if (!CCLayer::init()) { return false; } setTouchEnabled(true); return true; }
2).提升觸摸響應優先級為-128
void CTeachLayer::registerWithTouchDispatcher() { //使用-128和CCMenu優先級相同,並且吞掉事件true// CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, -128, true); CCLayer::registerWithTouchDispatcher(); }
3).在ccTouchBegan判斷觸點
bool CTeachLayer::ccTouchBegan( CCTouch* pTouch, CCEvent* pEvent ) { //得到觸摸位置 CCPoint touchPoint = pTouch->getLocation(); //聲明一個右下角100x50的矩形 CCRect m_obRect=CCRectMake( CCDirector::sharedDirector()->getVisibleSize().width-100, CCDirector::sharedDirector()->getVisibleSize().height-50, 100, 50); //判斷點是否在矩形中 if (m_obRect.containsPoint(touchPoint)) { return false; } return true; }
大功告成,快去試一下吧!
2.精確命中
手機上和電腦上的觸摸事件的區別在於:電腦上我們是用鼠標點擊,而手機上使用手指去摁,觸摸的精度的高低不言而喻!讓我們來看下面這張圖片:
讓我們看右上角的X號按鈕,在手機上點擊它來說應該是很困難的!他的真實尺寸應該是紅色矩形的區域(假設:50x50),為了讓玩家在引導時,能夠很方便的點擊到它,我們將實際的可觸摸區域設置為藍色區域(假設:100x100),這樣應該很好點到了吧!
這樣會有一個新的問題,如果點擊到紅色和藍色之間的區域,下面的x按鈕時響應不到的,那麼怎麼辦呢?我們需要修改touch的數據(設置為按鈕的正中心),然後touch事件將會以新的數據向下傳遞!這樣下面的按鈕就能響應到了!
讓我們看看代碼吧:
bool CTeachLayer::ccTouchBegan( CCTouch* pTouch, CCEvent* pEvent ) { CCPoint touchPoint = pTouch->getLocation(); if (!CGlobal::s_bTeach) { return false; } //假設按鈕在(300,200)的位置,那麼藍色矩形如下: CCRect m_obRect=CCRectMake( 250, 150, 100, 100); if (m_obRect.containsPoint(touchPoint)) { //得到藍色矩形的中心點(300,200) 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); return false; } return true; }
三.邏輯處理及代碼組織
這裡我大概說下新手引導的架構,代碼肯定貼不出來,太多太亂,說的不對的地方,歡迎大家拍磚吐槽!>_<
1.首先創建了一個CTeachLayer繼承自CCLayer,添加到遊戲的最上層(UI層之上),記住,要先添加遊戲的其層,最後添加CTeachLayer,可以保存全局指針!
2.用一個枚舉記下你要引導的所有步驟,在根據枚舉值去設置高亮的位置及觸摸區域!可以記下當前引導的進度,以方便下次繼續引導!
3.遊戲邏輯中免不了要判斷引導(例:出第3波怪的時候引導玩家使用清屏道具),用全局的指針去設置引導的步驟!
4.引導完成後移除CTeachLayer,遊戲開始!
沒有留言:
張貼留言