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

原创 2013年12月03日 09:39:17

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


如何在层间或者场景间进行消息传递,大概是每个初学者都要面对的问题吧。这里介绍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

    //获得消息通知中心的一个单例对象
    static CCNotificationCenter *sharedNotificationCenter(void);

    //销毁通知中心的单例对象
    static void purgeNotificationCenter(void);
    
    //添加观察者
    void addObserver(CCObject *target, 
                     SEL_CallFuncO selector,
                     const char *name,
                     CCObject *obj);

    //移除观察者
    void removeObserver(CCObject *target,const char *name);
    
    //移除所有观察者
    int removeAllObservers(CCObject *target);
    
    //发送消息
    void postNotification(const char *name);

    //发送带数据的消息
    void postNotification(const char *name, CCObject *object);

观察者的意思即是等待获取消息的对象,比如上图的B。


3.原理

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


4.示例

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

//ALayer
bool ALayer::init()
{
	bool bRet=false;
	do 
	{
		CC_BREAK_IF(!CCLayer::init());
		CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
		CCMenuItemImage *pCloseItem = CCMenuItemImage::create(
			"CloseNormal.png",
			"CloseSelected.png",
			this,
			menu_selector(ALayer::PostMessage));//按钮用于点击发送消息

		pCloseItem->setAnchorPoint(ccp(0.5,0.5));
		pCloseItem->setPosition(ccp(visibleSize.width/2,visibleSize.height/2));
		CCMenu* pMenu = CCMenu::create(pCloseItem, NULL);
		pMenu->setPosition(CCPointZero);
		this->addChild(pMenu, 1);

		bRet=true;
	} while (0);
	return bRet;
}

void ALayer::PostMessage(CCObject* pSender)
{
	CCString* str=CCString::create("Hello BLayer!");
	CCNotificationCenter::sharedNotificationCenter()->postNotification("BMessage",str);//发送带str的消息BMessage
}

//BLayer
bool BLayer::init()
{
	bool bRet=false;
	do 
	{
		CC_BREAK_IF(!CCLayer::init());
		
		CCNotificationCenter::sharedNotificationCenter()->addObserver(this,callfuncO_selector(BLayer::getMessage),"BMessage",NULL);//注册BMessage,如果接收到了,执行getMessage

		bRet=true;
	} while (0);
	return bRet;
}

void BLayer::getMessage(CCObject* obj)
{
	CCString* str=static_cast<CCString*>(obj);//打印出传递的数据
	CCLog(str->getCString());
}

BLayer::~BLayer(void)
{
	CCNotificationCenter::sharedNotificationCenter()->purgeNotificationCenter();//释放通知中心单例对象
}

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


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

cocos2d-x 建立自己的层级窗口消息机制

在开发一些窗口层次比复杂的cocos2d项目时,会发现一些由于没有窗口层次而引起的bug。这些bug让一些从windows平台过来的人觉得很无奈。比如,我们有一个列表控件,我们在其中放了一些菜单,当我...

Cocos2dx 3.0rc事件监听和消息通知

1、新建一个存放数据的类 class AAA { public: CC_SYNTHESIZE(std::string, name, Name); CC_SYNTHESIZE(int, age, A...

消息机制在cocos2dx中的使用

设计精度的游戏趋向于事件驱动。即当一个事件发生了(发生了武器,扳动了手柄,一个犯错的警告等等), 事件被广播给游戏中有关的对象。这样它们可以恰当地 做出反应。这些事件一般是以一个数据包的形式送出, ...

【玩转cocos2d-x之二十六】数据结构CCDictionary

CCDictionary在cocos2d-x中被大量的应用,比如CCTexureCache,CCSpriteFramCache等等。 1.实现原理 1.1.uthash CCDiction...

【玩转cocos2d-x之二十五】数据结构CCArray

CCArray是从cocos2d中移植过来的,类似于Apple的NSMutableArray,但是比NSMutableArray更为的好用。要注意的是虽然CCArray和CCDictionary可以管...

cocos2d-x的初步学习二十八之爱消除一

这篇文章中,我们将模仿某个游戏来实现,首页我们做首界面,这里都是一些UI元素的布局,其中会涉及到一些动画,比如贝塞尔曲线,还有cctableview来显示我们的得分,做个排行榜,OK,下面我直接上代码...

玩转cocos2d-x(一)创建、生成、运行HelloWorld

因为最近项目需要,开始研究下cocos2d-x;关于cocos2d-x这里就不废话了。 作为一个程序员,凡事先从HelloWorld开始,这是我们的优良传统。 这里先说下如何创建一个cocos2d...
  • berdy
  • berdy
  • 2012年08月14日 21:08
  • 14845

【玩转cocos2d-x之二十三】多线程和同步03-图片异步加载

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

【玩转cocos2d-x之三十四】绘图:CCDrawingPrimitives和CCDrawNode

最近忙出翔了,这年过的也揪心。好久没来更新博客了,今天就来写一写cocos2d-x中图形的绘制。 1.概述 其实cocos2d-x封装了大量的opengl的绘图函数,我们可以很轻松的在游戏中调...

【玩转cocos2d-x之三十二】xml的解析

cocos2d-x中对xml的解析是采用的TinyXML库,而对plist的解析同时结合了CCDictionary来处理,这里简单介绍下cocos2d-x中解析xml的两种方式,也是常用的xml两个C...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【玩转cocos2d-x之二十八】cocos2d-x的消息和数据传递
举报原因:
原因补充:

(最多只允许输入30个字)