【COCOS2DX-游戏开发之二】 模态对话框

需求:用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# 

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值