------------------------------------------------------------
定时调度器 CCScheduler
CCScheduler可以算是个计时器(单例),可以根据需要通过此类下的各种方法设定计时来执行回调函数,达到计时控制精灵、动画的作用。官方原例中已经演示了这个类的具体使用方法,这里就记录一下使用方法:
1.setTimeScale
用于减慢或者快进动画,其默认参数值为1.0,低于此值时计时器会放慢,否则加快,下面是代码:
class SchedulerTimeScale : public cocos2d::CCLayer { public: void onEnter(); void onExit(); CCControlSlider* sliderCtl(); void sliderAction(CCObject* pSender, CCControlEvent controlEvent); CCControlSlider* m_pSliderCtl; CREATE_FUNC(SchedulerTimeScale); };
cpp
CCControlSlider* SchedulerTimeScale::sliderCtl() { //添加一个滑动条用来控制动画速度 CCControlSlider * slider = CCControlSlider::create("sliderTrack2.png","sliderProgress2.png" ,"sliderThumb.png"); //滑动条数值产生变化时调用自定义的sliderAction来执行setTimeScale slider->addTargetWithActionForControlEvents(this, cccontrol_selector(SchedulerTimeScale::sliderAction), CCControlEventValueChanged); slider->setMinimumValue(-3.0f); slider->setMaximumValue(3.0f); slider->setValue(1.0f); return slider; } void SchedulerTimeScale::sliderAction(CCObject* pSender, CCControlEvent controlEvent) { CCControlSlider* pSliderCtl = (CCControlSlider*)pSender; float scale; scale = pSliderCtl->getValue(); //这里由导演取得所有动画的计时器并执行setTimeScale CCDirector::sharedDirector()->getScheduler()->setTimeScale(scale); } void SchedulerTimeScale::onEnter() { CCLayer::onEnter(); CCSize s = CCDirector::sharedDirector()->getWinSize(); // rotate and jump CCActionInterval *jump1 = CCJumpBy::create(4, ccp(-s.width+80,0), 100, 4); CCActionInterval *jump2 = jump1->reverse(); CCActionInterval *rot1 = CCRotateBy::create(4, 360*2); CCActionInterval *rot2 = rot1->reverse(); CCSequence* seq3_1 = CCSequence::create(jump2, jump1, NULL); CCSequence* seq3_2 = CCSequence::create(rot1, rot2, NULL); CCFiniteTimeAction* spawn = CCSpawn::create(seq3_1, seq3_2, NULL); CCRepeat* action = CCRepeat::create(spawn, 50); CCRepeat* action2 = (CCRepeat*)action->copy()->autorelease(); CCRepeat* action3 = (CCRepeat*)action->copy()->autorelease(); CCSprite *grossini = CCSprite::create("grossini.png"); CCSprite *tamara = CCSprite::create("grossinis_sister1.png"); CCSprite *kathia = CCSprite::create("grossinis_sister2.png"); grossini->setPosition(ccp(40,80)); tamara->setPosition(ccp(40,80)); kathia->setPosition(ccp(40,80)); addChild(grossini); addChild(tamara); addChild(kathia); grossini->runAction(CCSpeed::create(action, 0.5f)); tamara->runAction(CCSpeed::create(action2, 1.5f)); kathia->runAction(CCSpeed::create(action3, 1.0f)); m_pSliderCtl = sliderCtl(); m_pSliderCtl->setPosition(ccp(s.width / 2.0f, s.height / 3.0f)); addChild(m_pSliderCtl); } void SchedulerTimeScale::onExit() { // restore scale 还原timeScale的默认值 CCDirector::sharedDirector()->getScheduler()->setTimeScale(1); CCLayer::onExit(); }
2.scheduleUpdateForTarget
有时需要不同的计时器来各自控制精灵或者动画,这就需要为不同的精灵或者动画关联不同的scheduler了,下面是代码:
//自定义两个Schedulers class TwoSchedulers : public cocos2d::CCLayer { public: void onEnter(); CCControlSlider* sliderCtl(); void sliderAction(CCObject* sender, CCControlEvent controlEvent); //这里定义两个Scheduler cocos2d::CCScheduler *sched1; cocos2d::CCScheduler *sched2; //动作管理器用来统一管理所有关联对象的动作 cocos2d::CCActionManager *actionManager1; cocos2d::CCActionManager *actionManager2; CCControlSlider *sliderCtl1; CCControlSlider *sliderCtl2; CREATE_FUNC(TwoSchedulers); };
cpp
CCControlSlider *TwoSchedulers::sliderCtl() { // CGRect frame = CGRectMake(12.0f, 12.0f, 120.0f, 7.0f); CCControlSlider *slider = CCControlSlider::create("sliderTrack2.png","sliderProgress2.png" ,"sliderThumb.png"); //[[UISlider alloc] initWithFrame:frame]; slider->addTargetWithActionForControlEvents(this, cccontrol_selector(TwoSchedulers::sliderAction), CCControlEventValueChanged); slider->setMinimumValue(0.0f); slider->setMaximumValue(2.0f); //slider.continuous = YES; slider->setValue(1.0f); return slider; } void TwoSchedulers::sliderAction(CCObject* sender, CCControlEvent controlEvent) { float scale; CCControlSlider *slider = (CCControlSlider*) sender; scale = slider->getValue(); if( sender == sliderCtl1 ) sched1->setTimeScale(scale); else sched2->setTimeScale(scale); } void TwoSchedulers::onEnter() { CCLayer::onEnter(); CCSize s = CCDirector::sharedDirector()->getWinSize(); // rotate and jump CCActionInterval *jump1 = CCJumpBy::create(4, ccp(0,0), 100, 4); CCActionInterval *jump2 = jump1->reverse(); CCSequence* seq = CCSequence::create(jump2, jump1, NULL); CCRepeatForever* action = CCRepeatForever::create(seq); // Center CCSprite *grossini = CCSprite::create("grossini.png"); addChild(grossini); grossini->setPosition(ccp(s.width/2,100)); grossini->runAction((CCAction*)action->copy()->autorelease()); CCScheduler *defaultScheduler = CCDirector::sharedDirector()->getScheduler(); // Left: // Create a new scheduler, and link it to the main scheduler //创建计时器并且关联到主计时器 sched1 = new CCScheduler(); defaultScheduler->scheduleUpdateForTarget(sched1, 0, false); // Create a new ActionManager, and link it to the new scheudler //创建动作管理器并关联到自定义的计时器 actionManager1 = new CCActionManager(); sched1->scheduleUpdateForTarget(actionManager1, 0, false); for( unsigned int i=0; i < 10; i++ ) { CCSprite *sprite = CCSprite::create("grossinis_sister1.png"); // IMPORTANT: Set the actionManager running any action //将精灵加入到动作管理器中统一动作 sprite->setActionManager(actionManager1); addChild(sprite); sprite->setPosition(ccp(30+15*i,100)); sprite->runAction((CCAction*)action->copy()->autorelease()); } // Right: // Create a new scheduler, and link it to the main scheduler sched2 = new CCScheduler();; defaultScheduler->scheduleUpdateForTarget(sched2, 0, false); // Create a new ActionManager, and link it to the new scheudler actionManager2 = new CCActionManager(); sched2->scheduleUpdateForTarget(actionManager2, 0, false); for( unsigned int i=0; i < 10; i++ ) { CCSprite *sprite = CCSprite::create("grossinis_sister2.png"); // IMPORTANT: Set the actionManager running any action sprite->setActionManager(actionManager2); addChild(sprite); sprite->setPosition(ccp(s.width-30-15*i,100)); sprite->runAction((CCAction*)action->copy()->autorelease()); } //创建两个滑动条 sliderCtl1 = sliderCtl(); addChild(sliderCtl1); sliderCtl1->retain(); sliderCtl1->setPosition(ccp(s.width / 4.0f, s.height - 20)); sliderCtl2 = sliderCtl(); addChild(sliderCtl2); sliderCtl2->retain(); sliderCtl2->setPosition(ccp(s.width / 4.0f*3.0f, s.height-20)); }
上面添加的两个层在同一场景,拖动中间的滑动条将会看到所有动画都受它的参数影响,而拖动顶上两个滑动条时却只能影响为其自定义关联的精灵和动画。
3.暂停、唤醒、移除计时器
void HelloWorld::menuCloseCallback(CCObject* pSender) { // "close" menu item clicked //CCDirector::sharedDirector()->end(); //这里把关闭按钮执行的代码改成了暂停与唤醒计时器的代码,不过这里是停止、唤醒所有计时器 if (isPause==false){ m_pPausedTargets=CCDirector::sharedDirector()->getScheduler()->pauseAllTargets(); isPause=true; CC_SAFE_RETAIN(m_pPausedTargets); }else{ CCDirector::sharedDirector()->getScheduler()->resumeTargets(m_pPausedTargets); isPause=false; } //这句用来移除所有计时器 //CCDirector::sharedDirector()->getScheduler()->unscheduleAll(); }
在官方interval test 一例中还使用Schedule做了计时器:
//开始计时,这个是CCNode中的函数,用于每秒执行一次回调函数,也可以后面加延时调用的参数 schedule(schedule_selector(HelloWorld::gameTimer));
里面还有个更常用的相当于暂停、继续游戏的方法:
void IntervalLayer::onPause(CCObject* pSender) { if(CCDirector::sharedDirector()->isPaused()) CCDirector::sharedDirector()->resume(); else CCDirector::sharedDirector()->pause(); }
关于CCScheduler,其它还有很多方法,说是说不完了,得到源代码和官方原例中里自己研究了……
源码:http://download.csdn.net/detail/cyistudio/5467885
转自:http://blog.csdn.net/zhuzhihai1988/article/details/9088105
-------------------------------------差一点就永远的分割线-----------------------------------------------------------------------------一条不够所以加一条的----------------------------------------
update 定时器,每一帧都被触发,使用 scheduleUpdate 方法来启用; schedule 定时器,可以设置触发的间隔,使用 schedule 方法来启用。
1.调度器可以随时增删或修改被注册的定时器。具体来看,调度器将 update 定时器与普通定时器分别处理:当某个节点注册 update 定时器时,调度器就会把节点添加到 Updates 容器中,为了提高调度器效率,Cocos2d-x 使用了散列表与链表结合 的方式来保存定时器信息;当某个节点注册普通定时器时,调度器会把回调函数和其他信息保存到 Selectors 散列表中。
Schedule 定时器
首先,什么是定时器呢?或许你有时候会想让某个函数不断的去执行,或许只是执行一次,获取你想让他每隔几秒执行一次,ok,这些都可以统统交给定时器来解决。
cocos2dx中有三种定时器:schedule,scheduleUpdate,scheduleOnce。了解其功能便会发现定时器真是太方便了,废话不多说,我们逐一学习一下。
1、scheduleUpdate
scheduleUpdate,但是这个时候我们需要重写CCObject中的update方法,初始化scheduleUpdate有两种方法:
1,可以在自己的init方法中初始化它。
2,可在onEnter中初始化它,但是一定要CCLayer::onEnter()否则执行不到你的update
加入当前节点后,程序会每帧都会自动执行一次默认的Update函数。(注:一定是Update函数哦,若想调用其他自己命名的函数则使用schedule) 看例子,走起。 首先在HelloWord类的头文件(HelloWord.h)中声明Update函数:
void Update(float dt); //注意参数类型
然后在HelloWorld类源文件(HelloWorld.cpp)中实现函数Update:
void HelloWorld::Update(float dt) { CCLOG("baibai"); }
现在我们可以调用了,在需要他不断执行的地方加入调用的代码就ok:
this->scheduleUpdate(); //this是当前节点,如layer,所以可以省略啦。
运行之后你将会看到不断有baibai被打印出来 ... ...
2、schedule
可以没隔几秒执行某个自定义的函数,来看代码: 首先还是在HelloWorld头文件(HelloWord.h)中声明所要执行的函数:
void Move(float dt);
然后在HelloWorld类源文件(HelloWorld.cpp)中实现函数Update:
void HelloWorld::Move(float dt) { CCLOG("moving ..."); }
现在去执行他,注意参数哦
this->schedule(schedule_selector(HelloWorld::Move), 2.0f); //每隔2.0f执行一次,省略参数则表示每帧都要执行
运行之后,"moving ... "每隔1.0f才会被打印一次。
3、scheduleOnce
功能:在几秒之后执行,并且只会执行一次。 我们就执行上面所写的Move函数吧。
this->scheduleOnce(schedule_selector(HelloWorld::Move), 3.0f); //在3.0f之后执行,并且只执行一次。
运行一下,baibai只是被打印了一次就完了。。。 ok,定时器的调用已经讲完了,大家不妨自己写一些函数体验一下。
但是怎么停止定时器呢?
1、停止执行自己定义的函数定时器:
this->unschedule(schedule_selector(HelloWorld::Move));
2、停止默认定时器:
this->unscheduleUpdate();
3、停止所有定时器:
this->unscheduleAllSelectors();