Cocos2d-x 游戲暫停和觸摸屏蔽

2018-10-02 09:54 更新

游戲暫停和觸摸屏蔽

一個(gè)游戲打到一半尿點(diǎn)咋整?難道要憋著。。。這不科學(xué)?。?/p>

好吧,把暫停游戲和恢復(fù)游戲的功能加進(jìn)去吧,否則也太對不起觀眾了!

1.暫停功能的加入

再給游戲加個(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)行替換。

2.游戲暫停狀態(tài)下的觸摸問題

如果就這么完了,那也弱爆了。。。游戲的調(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)
    {
    }

3.第三種暫停屏蔽觸摸的方法

因?yàn)橛螒蛑挥兄鹘强梢员挥|摸移動,所以只在PlaneLayer中的MoveTo函數(shù)里,做如下判斷:

    if(isAlive && !CCDirector::sharedDirector()->isPaused())

這樣就夠了。如果游戲暫停就不讓飛機(jī)移動。好像也沒有什么問題。

效果圖(暫停狀態(tài))


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號