【玩转cocos2d-x之二十八】cocos2d-x的消息和数据传递

原创作品,转载请标明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

  1. //获得消息通知中心的一个单例对象
  2. staticCCNotificationCenter*sharedNotificationCenter(void);
  3. //销毁通知中心的单例对象
  4. staticvoidpurgeNotificationCenter(void);
  5. //添加观察者
  6. voidaddObserver(CCObject*target,
  7. SEL_CallFuncOselector,
  8. 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);
  9. //移除观察者
  10. voidremoveObserver(CCObject*target,char*name);
  11. //移除所有观察者
  12. intremoveAllObservers(CCObject*target);
  13. //发送消息
  14. voidpostNotification(//发送带数据的消息
  15. 观察者的意思即是等待获取消息的对象,比如上图的B。


    3.原理

    CCNotificationCenter的实现比较简单,它的内部维护了一个CCArray数组,数组的元素是CCNotificationObserver类型的对象,CCNotificationObserver封装了回调的执行者,回调函数,消息名称以及传递的数据。每次注册,也就是添加观察者,其实就是把这个CCNotificationObserver对象加入通知中心的CCArray数组,而每次的消息发送就是将消息传递给通知中心,由通知中心遍历这个数组,找到一致的消息,调用这些回调函数。其实这样看起来,就像是A在调用B的函数。具体的就自己看下源码吧。


    4.示例

    这里做了一个场景,包含了2个层,目的是层A向层B发送带数据的消息,层B收到后打印出这条数据。

    //ALayer
  1. boolALayer::init()
  2. {
  3. boolbRet=false;
  4. do
  5. {
  6. CC_BREAK_IF(!CCLayer::init());
  7. CCSizevisibleSize=CCDirector::sharedDirector()->getVisibleSize();
  8. CCMenuItemImage*pCloseItem=CCMenuItemImage::create(
  9. "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",
  10. 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));//按钮用于点击发送消息
  11. pCloseItem->setAnchorPoint(ccp(0.5,0.5));
  12. pCloseItem->setPosition(ccp(visibleSize.width/2,visibleSize.height/2));
  13. CCMenu*pMenu=CCMenu::create(pCloseItem,NULL);
  14. pMenu->setPosition(CCPointZero);
  15. this->addChild(pMenu,1);
  16. bRet=true;
  17. }while(0);
  18. returnbRet;
  19. }
  20. voidALayer::PostMessage(CCObject*pSender)
  21. CCString*str=CCString::create("HelloBLayer!");
  22. CCNotificationCenter::sharedNotificationCenter()->postNotification("BMessage",str);//发送带str的消息BMessage
  23. //BLayer
  24. boolBLayer::init()
  25. false;
  26. do
  27. CC_BREAK_IF(!CCLayer::init());
  28. CCNotificationCenter::sharedNotificationCenter()->addObserver("BMessage",NULL);//注册BMessage,如果接收到了,执行getMessage
  29. bRet=true;
  30. }while(0);
  31. returnbRet;
  32. }
  33. voidBLayer::getMessage(CCObject*obj)
  34. CCString*str=static_cast<CCString*>(obj);//打印出传递的数据
  35. CCLog(str->getCString());
  36. BLayer::~BLayer(void)
  37. CCNotificationCenter::sharedNotificationCenter()->purgeNotificationCenter();//释放通知中心单例对象
  38. }

5.注意

使用CCNotificationCenter需要注意以下几点:

(1)一个对象可以注册多个消息,一个消息也可以由多个消息注册。

(2)传递参数,A可以向B传递参数,而B在注册的时候也可以带一个参数,如果这两个数据不是指向同一对象的话,消息不会传递。也就是说要么A传递NULL对象,要么B注册时带NULL对象,要么都不是NULL但必须是同一对象,消息传递才会成功。以下是发送消息执行的判断:

    if(!strcmp(name,observer->getName())&&(observer->getObject()==object||observer->getObject()==NULL||object==NULL))
(3)局部变量的传递,注意到上例,传递的是CCString的一个局部变量(但还是要autorelease),从CCNotificationCenter的实现上来看,这是没有问题的,因为数据是在postNotification被调用的,也就是整个函数体并没结束,数据不会被销毁。


6.效果图




7.源码下载

http://download.csdn.net/detail/jackyvincefu/6647453

相关文章

    本文实践自 RayWenderlich、Ali Hafizji 的文章《...
Cocos-code-ide使用入门学习地点:杭州滨江邮箱:appdevzw@1...
第一次開始用手游引擎挺激动!!!进入正题。下载资源1:从C...
    Cocos2d-x是一款强大的基于OpenGLES的跨平台游戏开发...
1.  来源 QuickV3sample项目中的2048样例游戏,以及最近《...
   Cocos2d-x3.x已经支持使用CMake来进行构建了,这里尝试...