一個(gè)游戲打到一半尿點(diǎn)咋整?難道要憋著。。。這不科學(xué)?。?/p>
好吧,把暫停游戲和恢復(fù)游戲的功能加進(jìn)去吧,否則也太對不起觀眾了!
再給游戲加個(gè)層叫ControlLayer,這個(gè)層包含了2個(gè)元素,暫停功能和分?jǐn)?shù)顯示功能。分?jǐn)?shù)顯示和本地存儲在后面介紹。
我們先看看暫停功能是怎么加入的。
//加入暫停按鈕
bool ControlLayer::init()
{
bool bRet=false;
do
{
CC_BREAK_IF(!CCLayer::init());
CCSize winSize=CCDirector::sharedDirector()->getWinSize();
//加入PauseMenu
CCSprite* normalPause=CCSprite::create(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("game_pause_nor.png"));
CCSprite* pressedPause=CCSprite::create(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("game_pause_pressed.png"));
pPauseItem=CCMenuItemImage::create();//創(chuàng)建CCMenuItem
pPauseItem->initWithNormalSprite(normalPause,pressedPause,NULL,this,menu_selector(ControlLayer::menuPauseCallback));//載入雙態(tài)圖和回調(diào)函數(shù)
pPauseItem->setPosition(ccp(normalPause->getContentSize().width/2+10,winSize.height-normalPause->getContentSize().height/2-10));
CCMenu *menuPause=CCMenu::create(pPauseItem,NULL);//創(chuàng)建CCMenu,可以這么理解CCMenuItem是CCMenu的孩子
menuPause->setPosition(CCPointZero);
this->addChild(menuPause,101);
bRet=true;
} while (0);
return bRet;
}
//暫停按鍵的回調(diào)函數(shù)
void ControlLayer::menuPauseCallback(CCObject* pSender)
{
if(!CCDirector::sharedDirector()->isPaused())//如果游戲處于正常狀態(tài)
{
//更改為恢復(fù)按鈕的雙態(tài)
pPauseItem->setNormalSpriteFrame(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("game_resume_nor.png"));
pPauseItem->setSelectedSpriteFrame(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("game_resume_pressed.png"));
CCDirector::sharedDirector()->pause();//暫停游戲,這是導(dǎo)演控制的
}
else//否則
{
//更改為暫停按鈕的雙態(tài)
pPauseItem->setNormalSpriteFrame(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("game_pause_nor.png"));
pPauseItem->setSelectedSpriteFrame(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("game_pause_pressed.png"));
CCDirector::sharedDirector()->resume();//開麥拉!
}
}
這里沒有使用CCMenuItemToggle的原因是它沒辦法實(shí)現(xiàn)一個(gè)圖案的兩個(gè)狀態(tài)(normal和pressed),所以這里我手動進(jìn)行替換。
如果就這么完了,那也弱爆了。。。游戲的調(diào)試過程中發(fā)現(xiàn)了這么一個(gè)問題,當(dāng)游戲暫停的時(shí)候,主角飛機(jī)仍然可以跟隨觸摸移動,這個(gè)bug就坑爹了,你可以在快掛掉的時(shí)候按下pause,把飛機(jī)挪到安全的位置,然后再按下resume,死不了了。。。
原來cocos2d-x在暫停CCScene之后觸摸仍然是有效的,所以我們需要在暫停之后屏蔽觸摸。
這個(gè)的解決方案主要是兩種:
(1)使用CCLayer的setTouchEnabled方法,但是這樣可能會引起程序的崩潰,因?yàn)橄到y(tǒng)在派發(fā)觸摸事件時(shí)發(fā)現(xiàn)響應(yīng)列表為空,會觸發(fā)一個(gè)斷言。
(2)寫一個(gè)NoTouchLayer,在這個(gè)層里響應(yīng)觸摸并吞噬觸摸操作,使比它游戲級低的無法接收到觸摸分發(fā)。但是優(yōu)先級又不能高于CCMenu,也就是-128,不然恢復(fù)按鈕也會被屏蔽,導(dǎo)致游戲無法恢復(fù),除非是同一優(yōu)先級。使用方法就是addChild和removeChild。關(guān)于觸摸事件和優(yōu)先級,請移步:,再次強(qiáng)調(diào),觸摸優(yōu)先級和addChild的Z軸順序無關(guān)。
//NoTouchLayer.h
class NoTouchLayer :
public CCLayer
{
public:
virtual bool init();
// implement the "static node()" method manually
LAYER_CREATE_FUNC(NoTouchLayer);
virtual void registerWithTouchDispatcher();
virtual bool ccTouchBegan (cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);
virtual void ccTouchMoved (cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);
virtual void ccTouchEnded (cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);
};
//NoTouchLayer.cpp
bool NoTouchLayer::init(){
if (!CCLayer::init() )
{
return false;
}
setTouchEnabled(true);//設(shè)置觸摸有效
return true;
}
void NoTouchLayer::registerWithTouchDispatcher()
{
CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, -127 , true);//優(yōu)先級低于-128(CCMenu),同時(shí)高于其他層(0),true表示吞噬觸摸
CCLayer::registerWithTouchDispatcher();
}
bool NoTouchLayer::ccTouchBegan (CCTouch *pTouch, CCEvent *pEvent)
{
return true;//返回true接收觸摸
}
void NoTouchLayer::ccTouchMoved (CCTouch *pTouch, CCEvent *pEvent)
{
}
void NoTouchLayer::ccTouchEnded (CCTouch *pTouch, CCEvent *pEvent)
{
}
因?yàn)橛螒蛑挥兄鹘强梢员挥|摸移動,所以只在PlaneLayer中的MoveTo函數(shù)里,做如下判斷:
if(isAlive && !CCDirector::sharedDirector()->isPaused())
這樣就夠了。如果游戲暫停就不讓飛機(jī)移動。好像也沒有什么問題。
效果圖(暫停狀態(tài))
更多建議: