在开发游戏的时候我们经常需要在层与层之间、场景与场景之间传递数据和消息,Cocos2dx框架应用观察者模式为我们封装了一个CCNotificationCenter类,也叫消息通知中心,它也是一个单例类。

    什么是观察者模式?看我的另一篇文章:设计模式C++实现——观察者模式

    从观察者模式来讲,CCNotificationCenter类是观察者模式中的目标对象(主题),而CCNotificationObserver则是观察者。一个目标对象可以注册多个观察者,当目标对象的状态改变的时候,可以通知观察者对象作出相应的反应,这是标准的观察者模式的实现。但是CCNotificationCenter稍微有些许差别,CCNotificationCenter不是通过自身状态改变来通知观察者,而是通过显式地发送观察者感兴趣的消息来通知它们,消息名称则是用来标识观察者是否感兴趣。每次消息传递给CCNotificationCenter,CCNotificationCenter就会遍历所有的观察者,找到注册了该消息标识符的观察者,然后将消息发送给它们。

    下面看一下这个类的API:

/** 获取CCNotificationCenter的单例类 */
static CCNotificationCenter *sharedNotificationCenter(void);

/** 销毁CCNotificationCenter的单例类 */
static void purgeNotificationCenter(void);

/** 将一个特定的对象添加为观察者
 *  target: 注册为观察者的对象
 *  selector: 当收到指定消息时的回调函数
 *  name: 消息名称,唯一标识符
 *  obj: 传递给回调函数的额外的参数
 */
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);


上一篇说到使用CCTableView类实现了好友列表,然后我们需要创建一个好友详细信息的界面,当在列表中点击某个好友时,跳转到详细界面显示该好友的详细信息。这个时候就需要在两个层(或者说两个场景)之间传递数据,下面我们做一下小测试:

首先新建一个好友详细信息场景,并添加为观察者,以监听消息:

FriendDetailScene.h

#ifndef __FRIEND_DETAIL_SCENE_H__
#define __FRIEND_DETAIL_SCENE_H__

#include "cocos2d.h"
#include "cocos-ext.h"

class FriendDetail : public cocos2d::CCLayer
{
public:
	FriendDetail();
	~FriendDetail();
	virtual bool init();

	static cocos2d::CCScene* scene();

	void backToPrior(CCObject* pSender);

	void getMessage(CCObject* obj);

	CREATE_FUNC(FriendDetail);
};

#endif

FriendDetailScene.cpp

从代码中可以看出,我们在init()初始化时注册了观察者,监听名为“selected_cell”的消息,当收到这个消息时,就会执行getMessage( CCObeject* obj )函数。一般接收通知的一方在接收完通知后需要removeObserver(移除监听)或者purgeNotificationCenter(销毁通知中心)。


然后我们就可以在好友列表层FriendListLayer的tableCellTouched( CCTableView* table, CCTableViewCell* cell )添加发送消息的相关代码:

void FriendListLayer::tableCellTouched( CCTableView* table, CCTableViewCell* cell )
{
	//CCLOG("Cell touched at index: %i", cell->getIdx()+1);
	// 一定要先注册监听,然后发送消息,这样才可以实现数据的传递。
	CCScene* pScene = FriendDetail::scene();
	CCDirector::sharedDirector()->pushScene(pScene);

	CCNotificationCenter::sharedNotificationCenter()->postNotification("selected_cell", (CCObject*)cell);
}
这里是将被点击的单元格cell传递过去,当FriendDetailLayer接收到cell时可以获取它的idx,这样就实现了数据的传递。


注意:如果改成下面这样将无法传递数据...

void FriendListLayer::tableCellTouched( CCTableView* table, CCTableViewCell* cell )
{
	//CCLOG("Cell touched at index: %i", cell->getIdx()+1);
	CCNotificationCenter::sharedNotificationCenter()->postNotification("selected_cell", (CCObject*)cell);

	CCScene* pScene = FriendDetail::scene();
	CCDirector::sharedDirector()->pushScene(pScene);
}

因为添加监听(addObserver)和发送消息(postNotification)是有先后顺序的,一定要先注册监听,然后发送消息,这样才可以实现数据的传递。


测试效果:

【Cocos2dx游戏开发】CCNotificationCenter传递消息和数据


【Cocos2dx游戏开发】CCNotificationCenter传递消息和数据



相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-01-03
  • 2021-06-02
  • 2021-09-16
  • 2022-01-14
  • 2021-10-10
  • 2022-12-23
猜你喜欢
  • 2021-10-10
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-08-26
  • 2021-07-27
  • 2021-10-09
相关资源
相似解决方案