動畫是游戲的必然要素之一,在整個游戲過程中,又有着加速、減速動畫的需求。以塔防為例子,布塔的時候希望能夠將游戲減速,布好塔后,則希望能將游戲加速;當某個怪被冰凍后,移動速度減緩,而其他怪的移動速度不變。cocos2d-x引擎為我們提供了很強大的接口,下面就將我實驗的過程復述一遍,也方便他人。
1)實現全局的加速、減速。
通過設置Scheduler的timeScale,可以實現全局的加、減速。代碼非常簡單:
CCScheduler* pScheduler = CCDirector::sharedDirector()->getScheduler(); pScheduler->setTimeScale(2.0f); //實現加速效果 pScheduler->setTimeScale(0.5f);//實現減速效果
2)實現對某個CCActionInterval動作的加速、減速
方法一:很容易想到的一個方法就是改變CCAnimation的delay unit。代碼如下:
CCAnimation* pAnimation = CCAnimationCache::sharedAnimationCache()->animationByName(“xxx”); pAnimation->setDelayUnit(pAnimation->getDelayUnit()*0.2f); //速度為原來的5倍
這個方法有一個缺點:改變了CCAnimationCache中這個animation的delay unit。也就是說以后即使再從CCAnimationCache中獲取這個animation,其delay unit已經是原來的0.2倍了。
方法二:cocos2d-x提供了CCSpeed的類,可以實現動畫速度的調節。用法如下:
CCActionInterval* pActionInterval = CCMoveTo::create(5.0f, ccp(500.0f, 100.0f)); CCSpeed* pSpeed= CCSpeed::create(pActionInterval, 1.5f); //1.5倍速運行 CCSpeed* pSpeed1 = CCSpeed::create(pActionInterval, 0.2f);// 0.2倍速運行 pSprite->runAction(pSpeed);
注意,如果pSprite有已經運行的動作,要用pSprite->stopActionByTag()停掉之前的動作,不然兩個動作就疊加到一起了。
很多時候你的主角的動作利用CCAction來實現,移動則是在update刷幀函數或者一些選擇器的方法中進行的,那么為了讓你的主角慢動作比較逼真,那么Himi建議不要使用scheduleUpdate函數,因為這個你無法修改每次調用update的時間默認都是每幀都調用,那么你應該自己定義一個選擇器當刷邏輯的函數,這樣就能配合CCSpeed實現逼真慢動作拉~
3)對某個CCFiniteTimeAction類型動作的加速、減速
大部分時候,一個游戲人物的動作並非由單一一個CCActionInterval類型的動作構成,而是一串動作連起來,構成一個Sequence。用CCSequence::create(…)創建的對象都是CCFinteTimeAction類型的,CCSpeed並不適用。在CCSpeed類的說明里,明確指出”This action can’t be Sequenceable because it is not an CCIntervalAction”。那對於Sequence就束手無策了嗎?非也。cocos2d-x引擎自帶例子中,schedulerTest給我們展示了如何控制某個sprite的scheduler的timescale。廢話少說,直接看代碼。
在class TwoSchedulers中定義了兩個customer的scheduler和兩個CCActionManager。
CCScheduler *sched1; CCScheduler *sched2; CCActionManager *actionManager1; CCActionManager *actionManager2;
在onEnter函數中,分別對兩個sprite設置customer的ActionManager.
CCScheduler *defaultScheduler = CCDirector::sharedDirector()->getScheduler(); // 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); // Replace the default ActionManager with the new one. pSprite1->setActionManager(actionManager1);
通過以上的代碼,就可以通過改變sched1的timescale來改變pSprite1的動作的快慢了。有了這種方法,那么就可以放棄CCSpeed的那種方法了。