作者 小滕的世界,原文链接 http://blog.csdn.net/teng_ontheway/article/details/8349253
需求:用cocos2d-x开发游戏时 可能需要模态对话框 拦截下层消息
比如:购买等待模态对话框 我们点击购买按钮后不希望玩家再次点击购买 这时候我们最幸福的就是拥有一个模态对话框了
不知道咋在MAC上截图截的灰蒙蒙的...
实现原理:
模态对话框 能够拦截对话框所有下层的消息
cocos2d-x 消息处理优先级【-128,128】越小优先级越高
而菜单CCMenu kCCMenuHandlerPriority优先级 为-128
要想拦截模态对话框下层所有消息(包括菜单)
我们必须将的模态对话框优先级设置小于-128 这样就可以成功的拦截按钮的消息了
但是这样也意味着当前模态对话框的菜单消息(-128)也被拦截了
我们需要手动将消息传给模态对话框上的按钮进行处理
实现过程:
1.模态对话框派生自CCColorLayer 这样有个好处能处理触摸事件 还可以设置不透明度和背景颜色 比如半透明的灰色
- setColor(ccc3(255,0,0));
- setOpacity(128);
2.赋予当前模态对话框 一个接受触摸事件的最高优先级 意味着优先级数值要<-128 这样才能拦截包括按钮在内的所有消息
- // 屏蔽所有priority比自己大的消息
- CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, kCCMenuHandlerPriority - 1, true);
3.处理触摸消息 手动将消息传送给当前模态对话框的按钮 看他们是否处理
- bool DialogLayer::ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
- {
- // 因为拦截了所有消息(包括按钮) 所以需要将消息手动传给模态对话框上的按钮
- if (mMenu) {
- mTouchedMenu = mMenu->ccTouchBegan(pTouch, pEvent);
- }
- return true;
- }
简单的封装了一个类 还有待于改进 但目前已经能够满足使用了
- #ifndef _DIALOGLAYER_H_
- #define _DIALOGLAYER_H_
- #include "cocos2d.h"
- class DialogLayer: public cocos2d::CCLayerColor
- {
- public:
- DialogLayer();
- virtual ~DialogLayer();
- public:
- /** 初始化对话框 */
- virtual bool onInitDialog() = 0;
- /** 所有的菜单按钮压入到容器中 */
- void pushMenu(cocos2d::CCMenuItem *pMenu);
- virtual bool init();
- virtual void onEnter();
- virtual void onExit();
- 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);
- virtual void ccTouchCancelled(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);
- private:
- /** 初始化菜单 将菜单添加到模态对话框上*/
- bool initMenu();
- private:
- cocos2d::CCMenu *mMenu; // 模态对话框菜单
- cocos2d::CCArray *mMenuItemArray; // 所有菜单
- bool mTouchedMenu; // 记录菜单点击
- };
使用很简单:
1.派生一个对话框,重载实现OnInitDialog将需要的控件添加到模态对话框上
2.派生类中需要响应事件的按钮使用pushMenu添加
3.派生类实现CREATE_FUNC(class_name)宏
- class ExitDlg : public DialogLayer
- {
- public:
- virtual bool onInitDialog();
- CREATE_FUNC(ExitDlg);
- public:
- /** 确认和退出按钮 */
- void okMenuItemCallback(CCObject *obj);
- void cancelMenuItemCallback(CCObject *obj);
- };
- bool ExitDlg::onInitDialog()
- {
- CCSize winSize = CCDirector::sharedDirector()->getWinSize();
- CCLabelTTF *label = CCLabelTTF::create("Are you sure exit?", "", 64);
- label->setPosition(ccp(winSize.width / 2, winSize.height / 2 + 50));
- this->addChild(label);
- CCMenuItemFont *okMenuItem = CCMenuItemFont::create("OK", this, menu_selector(ExitDlg::okMenuItemCallback));
- okMenuItem->setPosition(ccp(winSize.width / 2 - 100, winSize.height / 2 - 50));
- CCMenuItemFont *cancelMenuItem = CCMenuItemFont::create("Cancel", this, menu_selector(ExitDlg::cancelMenuItemCallback));
- cancelMenuItem->setPosition(ccp(winSize.width / 2 + 100, winSize.height / 2 - 50));
- pushMenu(okMenuItem);
- pushMenu(cancelMenuItem);
- setColor(ccc3(255,0,0));
- setOpacity(128);
- return true;
- }
- void ExitDlg::okMenuItemCallback(CCObject *obj)
- {
- CCDirector::sharedDirector()->end();
- }
- void ExitDlg::cancelMenuItemCallback(CCObject *obj)
- {
- removeFromParentAndCleanup(true);
- }
使用也相当easy
- void HelloWorld::menuCloseCallback(CCObject* pSender)
- {
- ExitDlg* dlg = ExitDlg::create();
- addChild(dlg);
- }
剩下的就是不断的重复重复再重复的利用了 哈哈
代码如下:查看代码
原理文章可以参考oneRain 的 文章 感谢作者的亲情奉献 哈哈
http://blog.csdn.net/onerain88/article/details/7608496#