zoukankan      html  css  js  c++  java
  • CCNotificationCenter传递消息和数据

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

        从观察者模式来讲,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

    #include "FriendDetailScene.h"  
    
    USING_NS_CC;  
    USING_NS_CC_EXT;  
    
    FriendDetail::FriendDetail()  
    {  
    
    }  
    
    FriendDetail::~FriendDetail()  
    {  
        CCNotificationCenter::sharedNotificationCenter()->purgeNotificationCenter(); // 释放通知中心对象  
    }  
    
    CCScene* FriendDetail::scene()  
    {  
        CCScene *scene = CCScene::create();  
        FriendDetail *layer = FriendDetail::create();  
        scene->addChild(layer);  
        return scene;  
    }  
    
    bool FriendDetail::init()  
    {  
        if ( !CCLayer::init() )  
        {  
            return false;  
        }  
    
        CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();  
        CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();  
    
        // 背景  
        CCSprite* pSprite = CCSprite::create("IMG_Background.png");  
        pSprite->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));  
        this->addChild(pSprite, 0);  
    
        // 返回按钮  
        CCMenuItemImage *pBackItem = CCMenuItemImage::create(  
            "button1.png",  
            "button1.png",  
            this,  
            menu_selector(FriendDetail::backToPrior));     
        pBackItem->setPosition(680, 100);  
        CCMenu* pMenu = CCMenu::create(pBackItem, NULL);  
        pMenu->setPosition(CCPointZero);  
        this->addChild(pMenu, 1);  
    
        // 接收消息  
        CCNotificationCenter::sharedNotificationCenter()->addObserver(this, callfuncO_selector(FriendDetail::getMessage), "selected_cell", NULL);  
    
        return true;  
    }  
    
    void FriendDetail::backToPrior(CCObject* pSender)  
    {  
        CCDirector::sharedDirector()->popScene();  
    }  
    
    void FriendDetail::getMessage( CCObject* obj )  
    {  
        // 头像icon路径  
        std::string imagePath[10] = {"icon0.png","icon1.png","icon2.png","icon3.png","icon4.png","icon5.png","icon6.png","icon7.png","icon8.png","icon9.png"};  
    
        CCTableViewCell* cell = static_cast<CCTableViewCell*>(obj);  
        int idx = cell->getIdx();  
    
        CCSprite* iconSprite = CCSprite::create(imagePath[idx].c_str());  
        iconSprite->setPosition(ccp(400, 380));  
        this->addChild(iconSprite);  
    }  

    从代码中可以看出,我们在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)是有先后顺序的,一定要先注册监听,然后发送消息,这样才可以实现数据的传递。

  • 相关阅读:
    数位DP
    组合
    卢卡斯Lucas&扩展卢卡斯
    [HNOI2014]道路堵塞
    [模板]三维凸包(无讲解)
    [CF526G]Spiders Evil Plan
    [CCPC2019 ONLINE]H Fishing Master
    [CCPC2019 ONLINE]E huntian oy
    [CF1037H]Security
    [CF1037F]Maximum Reduction
  • 原文地址:https://www.cnblogs.com/laohaozi/p/12538280.html
Copyright © 2011-2022 走看看