鍍金池/ 教程/ Java/ 游戲暫停和觸摸屏蔽
游戲暫停和觸摸屏蔽
游戲場景過渡
碰撞檢測
跨平臺移植和廣告植入
批次渲染
觸摸事件和優(yōu)先級
背景音樂和音效
別急,先處理好CCScene和CCLayer的關系
自定義敵機精靈
UFO層特殊道具
主角的登場和幀動畫
引擎坐標系,錨點和背景滾動
分數的本地存儲
子彈層的處理
搞個飛機來玩玩

游戲暫停和觸摸屏蔽

一個游戲打到一半尿點咋整?難道要憋著。。。這不科學啊!

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

1.暫停功能的加入

再給游戲加個層叫ControlLayer,這個層包含了2個元素,暫停功能和分數顯示功能。分數顯示和本地存儲在后面介紹。

我們先看看暫停功能是怎么加入的。

    //加入暫停按鈕
    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)圖和回調函數
            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;
    }
    //暫停按鍵的回調函數
    void ControlLayer::menuPauseCallback(CCObject* pSender)
    {
        if(!CCDirector::sharedDirector()->isPaused())//如果游戲處于正常狀態(tài)
        {
            //更改為恢復按鈕的雙態(tài)
            pPauseItem->setNormalSpriteFrame(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("game_resume_nor.png"));
            pPauseItem->setSelectedSpriteFrame(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("game_resume_pressed.png"));
            CCDirector::sharedDirector()->pause();//暫停游戲,這是導演控制的
        }
        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的原因是它沒辦法實現一個圖案的兩個狀態(tài)(normal和pressed),所以這里我手動進行替換。

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

如果就這么完了,那也弱爆了。。。游戲的調試過程中發(fā)現了這么一個問題,當游戲暫停的時候,主角飛機仍然可以跟隨觸摸移動,這個bug就坑爹了,你可以在快掛掉的時候按下pause,把飛機挪到安全的位置,然后再按下resume,死不了了。。。

原來cocos2d-x在暫停CCScene之后觸摸仍然是有效的,所以我們需要在暫停之后屏蔽觸摸。

這個的解決方案主要是兩種:

(1)使用CCLayer的setTouchEnabled方法,但是這樣可能會引起程序的崩潰,因為系統(tǒng)在派發(fā)觸摸事件時發(fā)現響應列表為空,會觸發(fā)一個斷言。

(2)寫一個NoTouchLayer,在這個層里響應觸摸并吞噬觸摸操作,使比它游戲級低的無法接收到觸摸分發(fā)。但是優(yōu)先級又不能高于CCMenu,也就是-128,不然恢復按鈕也會被屏蔽,導致游戲無法恢復,除非是同一優(yōu)先級。使用方法就是addChild和removeChild。關于觸摸事件和優(yōu)先級,請移步:,再次強調,觸摸優(yōu)先級和addChild的Z軸順序無關。

    //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);//設置觸摸有效
        return true;
    }

    void NoTouchLayer::registerWithTouchDispatcher()
    {
        CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, -127 , true);//優(yōu)先級低于-128(CCMenu),同時高于其他層(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.第三種暫停屏蔽觸摸的方法

因為游戲只有主角可以被觸摸移動,所以只在PlaneLayer中的MoveTo函數里,做如下判斷:

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

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

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

http://wiki.jikexueyuan.com/project/cocos2d-x-getting-real/images/11.1.jpeg" alt="" />

上一篇:碰撞檢測下一篇:搞個飛機來玩玩