打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
【cocos2d-x入门实战】微信飞机大战之十一:游戏暂停和触摸屏蔽

原创作品,转载请标明http://blog.csdn.net/jackystudio/article/details/11999229

一个游戏打到一半尿点咋整?难道要憋着。。。这不科学啊!

好吧,把暂停游戏和恢复游戏的功能加进去吧,否则也太对不起观众了!


1.暂停功能的加入

再给游戏加个层叫ControlLayer,这个层包含了2个元素,暂停功能和分数显示功能。分数显示和本地存储在后面介绍。

我们先看看暂停功能是怎么加入的。

  1. //加入暂停按钮  
  2. bool ControlLayer::init()  
  3. {  
  4.     bool bRet=false;  
  5.     do   
  6.     {  
  7.         CC_BREAK_IF(!CCLayer::init());  
  8.   
  9.         CCSize winSize=CCDirector::sharedDirector()->getWinSize();  
  10.   
  11.         //加入PauseMenu  
  12.         CCSprite* normalPause=CCSprite::create(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("game_pause_nor.png"));  
  13.         CCSprite* pressedPause=CCSprite::create(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("game_pause_pressed.png"));  
  14.         pPauseItem=CCMenuItemImage::create();//创建CCMenuItem  
  15.         pPauseItem->initWithNormalSprite(normalPause,pressedPause,NULL,this,menu_selector(ControlLayer::menuPauseCallback));//载入双态图和回调函数  
  16.         pPauseItem->setPosition(ccp(normalPause->getContentSize().width/2+10,winSize.height-normalPause->getContentSize().height/2-10));  
  17.         CCMenu *menuPause=CCMenu::create(pPauseItem,NULL);//创建CCMenu,可以这么理解CCMenuItem是CCMenu的孩子  
  18.         menuPause->setPosition(CCPointZero);  
  19.         this->addChild(menuPause,101);  
  20.   
  21.         bRet=true;  
  22.     } while (0);  
  23.   
  24.     return bRet;  
  25. }  
  1. //暂停按键的回调函数  
  2. void ControlLayer::menuPauseCallback(CCObject* pSender)  
  3. {  
  4.     if(!CCDirector::sharedDirector()->isPaused())//如果游戏处于正常状态  
  5.     {  
  6.         //更改为恢复按钮的双态  
  7.         pPauseItem->setNormalSpriteFrame(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("game_resume_nor.png"));  
  8.         pPauseItem->setSelectedSpriteFrame(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("game_resume_pressed.png"));  
  9.         CCDirector::sharedDirector()->pause();//暂停游戏,这是导演控制的  
  10.     }  
  11.     else//否则  
  12.     {  
  13.         //更改为暂停按钮的双态  
  14.         pPauseItem->setNormalSpriteFrame(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("game_pause_nor.png"));  
  15.         pPauseItem->setSelectedSpriteFrame(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("game_pause_pressed.png"));  
  16.         CCDirector::sharedDirector()->resume();//开麦拉!  
  17.     }  
  18. }  
这里没有使用CCMenuItemToggle的原因是它没办法实现一个图案的两个状态(normal和pressed),所以这里我手动进行替换。


2.游戏暂停状态下的触摸问题

如果就这么完了,那也弱爆了。。。游戏的调试过程中发现了这么一个问题,当游戏暂停的时候,主角飞机仍然可以跟随触摸移动,这个bug就坑爹了,你可以在快挂掉的时候按下pause,把飞机挪到安全的位置,然后再按下resume,死不了了。。。


原来cocos2d-x在暂停CCScene之后触摸仍然是有效的,所以我们需要在暂停之后屏蔽触摸。


这个的解决方案主要是两种:

(1)使用CCLayer的setTouchEnabled方法,但是这样可能会引起程序的崩溃,因为系统在派发触摸事件时发现响应列表为空,会触发一个断言。

(2)写一个NoTouchLayer,在这个层里响应触摸并吞噬触摸操作,使比它游戏级低的无法接收到触摸分发。但是优先级又不能高于CCMenu,也就是-128,不然恢复按钮也会被屏蔽,导致游戏无法恢复,除非是同一优先级。使用方法就是addChild和removeChild。关于触摸事件和优先级,请移步:http://blog.csdn.net/jackystudio/article/details/11860007,再次强调,触摸优先级和addChild的Z轴顺序无关。

  1. //NoTouchLayer.h  
  2. class NoTouchLayer :  
  3.     public CCLayer  
  4. {  
  5. public:  
  6.     virtual bool init();     
  7.   
  8.     // implement the "static node()" method manually   
  9.     LAYER_CREATE_FUNC(NoTouchLayer);   
  10.   
  11.     virtual void registerWithTouchDispatcher();   
  12.   
  13.     virtual bool ccTouchBegan (cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);   
  14.     virtual void ccTouchMoved (cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);   
  15.     virtual void ccTouchEnded (cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);   
  16. };  
  17.   
  18. //NoTouchLayer.cpp  
  19. bool NoTouchLayer::init(){    
  20.     if (!CCLayer::init() )    
  21.     {    
  22.         return false;    
  23.     }    
  24.     setTouchEnabled(true);//设置触摸有效  
  25.     return true;    
  26. }    
  27.   
  28. void NoTouchLayer::registerWithTouchDispatcher()  
  29. {    
  30.     CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, -127 , true);//优先级低于-128(CCMenu),同时高于其他层(0),true表示吞噬触摸  
  31.     CCLayer::registerWithTouchDispatcher();    
  32. }    
  33.   
  34. bool NoTouchLayer::ccTouchBegan (CCTouch *pTouch, CCEvent *pEvent)  
  35. {       
  36.     return true;//返回true接收触摸  
  37. }    
  38.   
  39. void NoTouchLayer::ccTouchMoved (CCTouch *pTouch, CCEvent *pEvent)  
  40. {    
  41. }    
  42.   
  43. void NoTouchLayer::ccTouchEnded (CCTouch *pTouch, CCEvent *pEvent)  
  44. {    
  45. }    

3.第三种暂停屏蔽触摸的方法

上面两种方法我都没有使用。因为游戏只有主角可以被触摸移动,所以在PlaneLayer中的MoveTo函数里,做如下判断:

  1. if(isAlive && !CCDirector::sharedDirector()->isPaused())  
这样就够了。如果游戏暂停就不让飞机移动。好像也没有什么问题。


效果图(暂停状态)



本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
cocos2dx之触摸事件
手游中内存优化问题
cocos2d-x 关卡选择界面(CCScrollView的使用)
cocos2d
【玩转cocos2d-x之五】导演类CCDirector
cocos2d-x 2.0.4 封装组合框 ComboBox
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服