Cocos2dx学习第九章(schedule简介)

前端之家收集整理的这篇文章主要介绍了Cocos2dx学习第九章(schedule简介)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

本章简单介绍一下有关schedule和一个工具类:NotificationCenter。

1.有关schedule

关于他,我们主要简单知道怎么用就可以了,具体不进行深入探讨。
(1)scheduleupdate()和update(float dt)
这两者结合使用,把当前节点加入到队列中,这个节点就会在游戏运行的每一帧中调用一次update函数。参数float dt表示上次调用update到当前这次调用update所间隔的时间。
  1. this->scheduleUpdate();
  2. void HelloWorld::update();
(2)不用update函数调用自己重新设计的函数
  1. this->schedule(schedule_selector(HelloWorld::myUpdate));
  2. void HelloWorld::myUpdate(float dt);
指定回调函数时,常用*selector形式,常用的有:
  1. schedule_seclctor():常用语定时器回调函数函数无参数。
  2. callfunc_seclctor():常用于定义动作回调函数函数无参数。
  3. callfuncN_seclctor():常用于定义动作回调函数函数带一个Node*参数。
  4. callfuncND_seclctor():常用于定义菜单回调函数,但一个CCObject*参数。
  5. menu_seclctor:常用于定义菜单回调函数
指定固定时间的定时调用声明方法
  1. thsi->schedule(schedule_selector(HelloWorld::myupdate),2.0f);//两秒调用一次
调用一次的方式如下:
  1. this->scheduleOnce(schedule_selector(myupdate),2.0f);
(3)停止定时器的调用,unSchedule
  1. this->unscheduleUpdate();
  2. this->unschedule(schedule_selector(HelloWorld::myupdare));
  3. this->unshcduleAllSeclector();//all call back will stop
(4)schedule并非定时很精确
不管是默认的update还是自定义的update,都是在同一个线程里面,所以某个函数占用时间过长,那么其他函数调用的时间就有可能延后。所以schedule和scheduleOnce都存在这样的时间偏差。下面,我们用timerc类利用dt来进行时间累计,看看1秒的定时调用如何偏差;
  1. #ifndef _TIME_H_
  2. #define _TIME_H_
  3. #include"cocos2d.h"
  4. USING_NS_CC;
  5. class Timerc:public Node
  6. {
  7. public:
  8. CREATE_FUNC(Timerc);
  9. virtual bool init();
  10. virtual void update(float dt);
  11. void start();
  12. float getcurrenttime();
  13. private:
  14. float m_time;
  15. };
  16. #endif
  1. #include"Timer.h"
  2. bool Timerc::init()
  3. {
  4. return true;
  5. }
  6. void Timerc::update(float dt)
  7. {
  8. m_time += dt;
  9. log("Timer::update() %f",m_time);
  10. }
  11. float Timerc::getcurrenttime()
  12. {
  13. return m_time;
  14. }
  15. void Timerc::start()
  16. {
  17. m_time = 0;
  18. this->scheduleUpdate();
  19. }
以上这个类,纯粹用来计时。以检验下面一秒调用的偏差:
  1. #ifndef __HELLOWORLD_SCENE_H__
  2. #define __HELLOWORLD_SCENE_H__
  3.  
  4. #include "cocos2d.h"
  5. #include "Timer.h"
  6. class HelloWorld : public cocos2d::Layer
  7. {
  8. public:
  9. static cocos2d::Scene* createScene();
  10. virtual bool init();
  11. CREATE_FUNC(HelloWorld);
  12. void logic(float dt);
  13. void dosomthing(float dt);
  14. private:
  15. Timerc* m_timer;
  16. };
  17. #endif // __HELLOWORLD_SCENE_H__
  1. #include "HelloWorldScene.h"
  2. USING_NS_CC;
  3. Scene* HelloWorld::createScene()
  4. {
  5. auto scene = Scene::create();
  6. auto layer = HelloWorld::create();
  7. scene->addChild(layer);
  8. return scene;
  9. }
  10. bool HelloWorld::init()
  11. {
  12. if ( !Layer::init() )
  13. {
  14. return false;
  15. }
  16. m_timer = Timerc::create();
  17. this->addChild(m_timer);
  18. m_timer->start();
  19. this->schedule(schedule_selector(HelloWorld::logic),1.0f);
  20. this->schedule(schedule_selector(HelloWorld::dosomthing));
  21. return true;
  22. }
  23. void HelloWorld::logic(float dt)
  24. {
  25. log("Hello World::logic %f",m_timer->getcurrenttime());
  26. }
  27. void HelloWorld::dosomthing(float dt)
  28. {
  29. for(long i = 0; i < 99999999; i++);//耗时操作
  30. }
我们一秒调用一次logic,下面看看输出结果是怎样的:

可见,第27次调用的时候,已经是27.4秒了,延迟了。如果我们想要更准确的在指定时间调用函数,可以在update里面做判断,大于等于某值时去调用,这样相对来说,会比较精确。

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.传递的数据
以上就是最基本的消息函数
先实现一个类,用于订阅消息,他是一个层:
  1. #ifndef _OTHERLAYER_H_
  2. #define _OTHERLAYER_H_
  3. #include "cocos2d.h"
  4. using namespace cocos2d;
  5. class OtherLayer:public Layer
  6. {
  7. public:
  8. CREATE_FUNC(OtherLayer);
  9. virtual bool init();
  10. private:
  11. void testMsg(Ref* pData);
  12. };
  13. #endif
  1. #include"OtherLayer.h"
  2. bool OtherLayer::init()
  3. {
  4. if(!Layer::init())return false;
  5. //新建一个层,并订阅test消息
  6. NotificationCenter::getInstance()->addObserver(this,callfuncO_selector(OtherLayer::testMsg),"test",NULL);//这个NULL,也可添加我们要的信息,比如(Ref*)"other layer data"
  7. return true;
  8. }
  9. //消息回调
  10. void OtherLayer::testMsg(Ref* pData)
  11. {
  12. log("testMsg in OtherLayer");
  13. }
然后我们再实现一个发消息的类,如下:
  1. #include "HelloWorldScene.h"
  2. #include "OtherLayer.h"
  3. USING_NS_CC;
  4. Scene* HelloWorld::createScene()
  5. {
  6. auto scene = Scene::create();
  7. auto layer = HelloWorld::create();
  8. scene->addChild(layer);
  9. //将层添加到场景里面
  10. auto otherLayer = OtherLayer::create();
  11. scene->addChild(otherLayer);
  12.  
  13. return scene;
  14. }
  15. bool HelloWorld::init()
  16. {
  17. if ( !Layer::init() )
  18. {
  19. return false;
  20. }
  21. //3秒后发消息
  22. this->schedule(schedule_selector(HelloWorld::sendmsg),3.0f);
  23. return true;
  24. }
  25.  
  26. void HelloWorld::sendmsg(float dt)
  27. {
  28. //发布test消息
  29. NotificationCenter::getInstance()->postNotification("test",NULL);
  30. }
上面就是简单的收发消息方法来了。 没什么好讲的,会用,了解就行额

3.实现一个简单的观察者

  1. #ifndef _NOTIFYUTIL_H_
  2. #define _NOTIFYUTIL_H_
  3. #include"cocos2d.h"
  4. using namespace cocos2d;
  5. class NotifyUtil:public Ref
  6. {
  7. public:
  8. static NotifyUtil* getInstance();
  9. CREATE_FUNC(NotifyUtil);
  10. virtual bool init();
  11. //订阅消息
  12. void addObserver(const std::string & sMsgName,std::function<void (Ref*)>func);
  13. //发送消息
  14. void postNotification(const std::string &sMsgName,Ref* data);
  15. private:
  16. static NotifyUtil* m_NotifyUtil;
  17. //一个消息对已一系列注册者回调
  18. std::map<std::string,std::vector<std::function<void(Ref*)>>> m_funcMap;
  19. };
  20. #endif
  21. #include"NotifyUtil.h"
  22. NotifyUtil* NotifyUtil::m_NotifyUtil = NULL;
  23. NotifyUtil* NotifyUtil::getInstance()
  24. {
  25. if(m_NotifyUtil == NULL)
  26. {
  27. m_NotifyUtil = NotifyUtil::create();
  28. m_NotifyUtil->retain();
  29. }
  30. return m_NotifyUtil;
  31. }
  32.  
  33. bool NotifyUtil::init()
  34. {
  35. return true;
  36. }
  37.  
  38. void NotifyUtil::addObserver(const std::string & sMsgName,std::function<void(Ref*)> func)
  39. {
  40. if(m_funcMap.find(sMsgName) != m_funcMap.end())
  41. {
  42. //已经存在该消息回调函数列表,有人订阅了同样的消息
  43. std::vector<std::function<void(Ref*)>> &funcList = m_funcMap.at(sMsgName);
  44. funcList.push_back(func);//将新的订阅添加到回调列表里面
  45. }
  46. else
  47. {
  48. std::vector<std::function<void(Ref*)>> funcList;//新建一个列表
  49. funcList.push_back(func);
  50. m_funcMap[sMsgName] = funcList;//将新建的列表放到map中
  51. }
  52. }
  53.  
  54. void NotifyUtil::postNotification(const std::string& sMsgName,Ref* data)
  55. {
  56. if(m_funcMap.find(sMsgName) != m_funcMap.end())
  57. {
  58. std::vector<std::function<void(Ref*)>> funcList = m_funcMap.at(sMsgName);
  59. for(auto func:funcList)
  60. {
  61. func(data);
  62. }
  63. }
  64. }
测试用例
  1. bool HelloWorld::init()
  2. {
  3. if ( !Layer::init() )
  4. {
  5. return false;
  6. }
  7. //三个订阅
  8. NotifyUtil::getInstance()->addObserver("hongzong",[](Ref* data)
  9. {
  10. log("hongzong receive msg %s",data);
  11. });
  12. NotifyUtil::getInstance()->addObserver("hongzong",[](Ref* data)
  13. {
  14. log("this is di zong");
  15. });
  16. NotifyUtil::getInstance()->addObserver("hongzong",[](Ref* data)
  17. {
  18. log("this is bing zai");
  19. });
  20. NotifyUtil::getInstance()->postNotification("hongzong",(Ref*)"here");
  21. return true;
  22. }

猜你在找的Cocos2d-x相关文章