本章简单介绍一下有关schedule和一个工具类:NotificationCenter。
1.有关schedule
关于他,我们主要简单知道怎么用就可以了,具体不进行深入探讨。
(1)scheduleupdate()和update(float dt)
(2)不用update函数,调用自己重新设计的函数
- this->scheduleUpdate();
- void HelloWorld::update();
指定回调函数时,常用*selector形式,常用的有:
- this->schedule(schedule_selector(HelloWorld::myUpdate));
- void HelloWorld::myUpdate(float dt);
(3)停止定时器的调用,unSchedule
- this->scheduleOnce(schedule_selector(myupdate),2.0f);
(4)schedule并非定时很精确
- this->unscheduleUpdate();
- this->unschedule(schedule_selector(HelloWorld::myupdare));
- this->unshcduleAllSeclector();//all call back will stop
不管是默认的update还是自定义的update,都是在同一个线程里面,所以某个函数占用时间过长,那么其他函数被调用的时间就有可能延后。所以schedule和scheduleOnce都存在这样的时间偏差。下面,我们用timerc类利用dt来进行时间累计,看看1秒的定时调用如何偏差;
- #ifndef _TIME_H_
- #define _TIME_H_
- #include"cocos2d.h"
- USING_NS_CC;
- class Timerc:public Node
- {
- public:
- CREATE_FUNC(Timerc);
- virtual bool init();
- virtual void update(float dt);
- void start();
- float getcurrenttime();
- private:
- float m_time;
- };
- #endif
以上这个类,纯粹用来计时。以检验下面一秒调用的偏差:
- #include"Timer.h"
- bool Timerc::init()
- {
- return true;
- }
- void Timerc::update(float dt)
- {
- m_time += dt;
- log("Timer::update() %f",m_time);
- }
- float Timerc::getcurrenttime()
- {
- return m_time;
- }
- void Timerc::start()
- {
- m_time = 0;
- this->scheduleUpdate();
- }
- #ifndef __HELLOWORLD_SCENE_H__
- #define __HELLOWORLD_SCENE_H__
- #include "cocos2d.h"
- #include "Timer.h"
- class HelloWorld : public cocos2d::Layer
- {
- public:
- static cocos2d::Scene* createScene();
- virtual bool init();
- CREATE_FUNC(HelloWorld);
- void logic(float dt);
- void dosomthing(float dt);
- private:
- Timerc* m_timer;
- };
- #endif // __HELLOWORLD_SCENE_H__
我们一秒调用一次logic,下面看看输出结果是怎样的:
- #include "HelloWorldScene.h"
- USING_NS_CC;
- Scene* HelloWorld::createScene()
- {
- auto scene = Scene::create();
- auto layer = HelloWorld::create();
- scene->addChild(layer);
- return scene;
- }
- bool HelloWorld::init()
- {
- if ( !Layer::init() )
- {
- return false;
- }
- m_timer = Timerc::create();
- this->addChild(m_timer);
- m_timer->start();
- this->schedule(schedule_selector(HelloWorld::logic),1.0f);
- this->schedule(schedule_selector(HelloWorld::dosomthing));
- return true;
- }
- void HelloWorld::logic(float dt)
- {
- log("Hello World::logic %f",m_timer->getcurrenttime());
- }
- void HelloWorld::dosomthing(float dt)
- {
- for(long i = 0; i < 99999999; i++);//耗时操作
- }
2.有关NotificationCenter,观察者模式工具类
cocos2dx提供了一个不错的观察着模式工具类,NotificationCenter,我们来看看常用的函数和参数:
(1)addObserver(订阅消息)
Ref* target:要订阅消息的主体。
SEL_CallFuncO selector:消息回调函数。
const std::string& name:消息名称。
Ref* sender:要传递的数据。
(2)removeObserver(取消订阅消息)
Ref* target:取消订阅消息的主体。
const std::string& name:消息名称。
(3)postNotification(发布消息)
const std::string& name
or
const std::string& name,消息名称
Ref* sender.传递的数据
以上就是最基本的消息函数。
先实现一个类,用于订阅消息,他是一个层:
- #ifndef _OTHERLAYER_H_
- #define _OTHERLAYER_H_
- #include "cocos2d.h"
- using namespace cocos2d;
- class OtherLayer:public Layer
- {
- public:
- CREATE_FUNC(OtherLayer);
- virtual bool init();
- private:
- void testMsg(Ref* pData);
- };
- #endif
然后我们再实现一个发消息的类,如下:
- #include"OtherLayer.h"
- bool OtherLayer::init()
- {
- if(!Layer::init())return false;
- //新建一个层,并订阅test消息
- NotificationCenter::getInstance()->addObserver(this,callfuncO_selector(OtherLayer::testMsg),"test",NULL);//这个NULL,也可添加我们要的信息,比如(Ref*)"other layer data"
- return true;
- }
- //消息回调
- void OtherLayer::testMsg(Ref* pData)
- {
- log("testMsg in OtherLayer");
- }
上面就是简单的收发消息方法来了。 没什么好讲的,会用,了解就行额
- #include "HelloWorldScene.h"
- #include "OtherLayer.h"
- USING_NS_CC;
- Scene* HelloWorld::createScene()
- {
- auto scene = Scene::create();
- auto layer = HelloWorld::create();
- scene->addChild(layer);
- //将层添加到场景里面
- auto otherLayer = OtherLayer::create();
- scene->addChild(otherLayer);
- return scene;
- }
- bool HelloWorld::init()
- {
- if ( !Layer::init() )
- {
- return false;
- }
- //3秒后发消息
- this->schedule(schedule_selector(HelloWorld::sendmsg),3.0f);
- return true;
- }
- void HelloWorld::sendmsg(float dt)
- {
- //发布test消息
- NotificationCenter::getInstance()->postNotification("test",NULL);
- }
3.实现一个简单的观察者
测试用例
- #ifndef _NOTIFYUTIL_H_
- #define _NOTIFYUTIL_H_
- #include"cocos2d.h"
- using namespace cocos2d;
- class NotifyUtil:public Ref
- {
- public:
- static NotifyUtil* getInstance();
- CREATE_FUNC(NotifyUtil);
- virtual bool init();
- //订阅消息
- void addObserver(const std::string & sMsgName,std::function<void (Ref*)>func);
- //发送消息
- void postNotification(const std::string &sMsgName,Ref* data);
- private:
- static NotifyUtil* m_NotifyUtil;
- //一个消息对已一系列注册者回调
- std::map<std::string,std::vector<std::function<void(Ref*)>>> m_funcMap;
- };
- #endif
- #include"NotifyUtil.h"
- NotifyUtil* NotifyUtil::m_NotifyUtil = NULL;
- NotifyUtil* NotifyUtil::getInstance()
- {
- if(m_NotifyUtil == NULL)
- {
- m_NotifyUtil = NotifyUtil::create();
- m_NotifyUtil->retain();
- }
- return m_NotifyUtil;
- }
- bool NotifyUtil::init()
- {
- return true;
- }
- void NotifyUtil::addObserver(const std::string & sMsgName,std::function<void(Ref*)> func)
- {
- if(m_funcMap.find(sMsgName) != m_funcMap.end())
- {
- //已经存在该消息回调函数列表,有人订阅了同样的消息
- std::vector<std::function<void(Ref*)>> &funcList = m_funcMap.at(sMsgName);
- funcList.push_back(func);//将新的订阅者添加到回调列表里面
- }
- else
- {
- std::vector<std::function<void(Ref*)>> funcList;//新建一个列表
- funcList.push_back(func);
- m_funcMap[sMsgName] = funcList;//将新建的列表放到map中
- }
- }
- void NotifyUtil::postNotification(const std::string& sMsgName,Ref* data)
- {
- if(m_funcMap.find(sMsgName) != m_funcMap.end())
- {
- std::vector<std::function<void(Ref*)>> funcList = m_funcMap.at(sMsgName);
- for(auto func:funcList)
- {
- func(data);
- }
- }
- }
- bool HelloWorld::init()
- {
- if ( !Layer::init() )
- {
- return false;
- }
- //三个订阅者
- NotifyUtil::getInstance()->addObserver("hongzong",[](Ref* data)
- {
- log("hongzong receive msg %s",data);
- });
- NotifyUtil::getInstance()->addObserver("hongzong",[](Ref* data)
- {
- log("this is di zong");
- });
- NotifyUtil::getInstance()->addObserver("hongzong",[](Ref* data)
- {
- log("this is bing zai");
- });
- NotifyUtil::getInstance()->postNotification("hongzong",(Ref*)"here");
- return true;
- }