原创作品,转载请标明:http://www.jb51.cc/article/p-vwigfxeg-ep.html
如何在层间或者场景间进行消息传递,大概是每个初学者都要面对的问题吧。这里介绍cocos2d-x的一种消息/数据传递方式,内置的观察者模式,也称消息通知中心,CCNotificationCenter。
1.CCNotificationCenter
CCNotificationCenter是cocos2d-x提供的一个消息中心,类似于观察者模式,是一个单例类,用于辅助控制消息传递。大概工作原理如下图。
这里以A,B通讯为例,A,B可以是层间或者场景间。假如A要向B发送带数据的消息。那么
(1)B向小心中心注册一个bMsg的消息,告知消息中心,如果消息中心接收到bMsg,必须通知B,以便B采取相应的措施。
(2)A向消息中心发送bMsg消息。
(3)消息中心接收到bMsg,查询有谁在它这里注册了这个消息,发现是B,就通知B有人发送了bMsg。
(4)当然这个消息带有A要传递的数据,而B也不知道到底是谁给它发了bMsg这条消息,除非在传递的数据中指出。
2.相关API
- //获得消息通知中心的一个单例对象
- staticCCNotificationCenter*sharedNotificationCenter(void);
- @H_403_110@ //销毁通知中心的单例对象
- staticvoidpurgeNotificationCenter(void); @H_403_110@
- //添加观察者
- voidaddObserver(CCObject*target,
- SEL_CallFuncOselector,
- constchar*name,108); list-style:decimal-leading-zero outside; color:inherit; line-height:20px; margin:0px!important; padding:0px 3px 0px 10px!important"> CCObject*obj);
- //移除观察者
- voidremoveObserver(CCObject*target,char*name);
- //移除所有观察者
- intremoveAllObservers(CCObject*target);
- //发送消息
- voidpostNotification(//发送带数据的消息
-
观察者的意思即是等待获取消息的对象,比如上图的B。
3.原理
CCNotificationCenter的实现比较简单,它的内部维护了一个CCArray数组,数组的元素是CCNotificationObserver类型的对象,CCNotificationObserver封装了回调的执行者,回调函数,消息名称以及传递的数据。每次注册,也就是添加观察者,其实就是把这个CCNotificationObserver对象加入通知中心的CCArray数组,而每次的消息发送就是将消息传递给通知中心,由通知中心遍历这个数组,找到一致的消息,调用这些回调函数。其实这样看起来,就像是A在调用B的函数。具体的就自己看下源码吧。
4.示例
这里做了一个场景,包含了2个层,目的是层A向层B发送带数据的消息,层B收到后打印出这条数据。
- //ALayer
@H_403_110@ boolALayer::init()
- {
- boolbRet=false;
- do @H_403_110@ {
- CC_BREAK_IF(!CCLayer::init()); @H_403_110@ CCSizevisibleSize=CCDirector::sharedDirector()->getVisibleSize();
- CCMenuItemImage*pCloseItem=CCMenuItemImage::create( @H_403_110@ "CloseNormal.png",108); list-style:decimal-leading-zero outside; color:inherit; line-height:20px; margin:0px!important; padding:0px 3px 0px 10px!important"> "CloseSelected.png",
- this ,108); list-style:decimal-leading-zero outside; color:inherit; line-height:20px; margin:0px!important; padding:0px 3px 0px 10px!important"> menu_selector(ALayer::PostMessage));//按钮用于点击发送消息
- pCloseItem->setAnchorPoint(ccp(0.5,0.5)); @H_403_110@ pCloseItem->setPosition(ccp(visibleSize.width/2,visibleSize.height/2));
- CCMenu*pMenu=CCMenu::create(pCloseItem,NULL); @H_403_110@ pMenu->setPosition(CCPointZero);
- this ->addChild(pMenu,1);
- bRet=true; @H_403_110@ }while(0);
- returnbRet; @H_403_110@ }
- voidALayer::PostMessage(CCObject*pSender)
- CCString*str=CCString::create("HelloBLayer!");
- CCNotificationCenter::sharedNotificationCenter()->postNotification("BMessage",str);//发送带str的消息BMessage
- //BLayer
- boolBLayer::init()
- false;
- do
- CC_BREAK_IF(!CCLayer::init());
- CCNotificationCenter::sharedNotificationCenter()->addObserver("BMessage",NULL);//注册BMessage,如果接收到了,执行getMessage
- bRet=true;
- }while(0);
- returnbRet;
- }
- voidBLayer::getMessage(CCObject*obj)
- CCString*str=static_cast<CCString*>(obj);//打印出传递的数据 @H_403_110@ CCLog(str->getCString());
- BLayer::~BLayer(void)
- CCNotificationCenter::sharedNotificationCenter()->purgeNotificationCenter();//释放通知中心单例对象 @H_403_110@ }