Cocos2d-x的Director提供了pushScene,replaceScene和popScene兩個函數來負責控制場景的切換,使用pushScene和replaceScene時可以傳入TransitionScene作爲參數來實現讓當前Scene以某種過渡跳轉到下一個Scene,但是當需要使用popScene彈出當前場景,而又想加入過渡動畫的話,引擎卻是沒有提供popSceneWithTransition之類的函數了。要實現popScene時也有過渡的話,從Cocos2d-x的論壇上看到一篇討論關於如何實現popSceneWithTransition的帖子,鏈接如下:
http://discuss.cocos2d-x.org/t/tip-implement-popscene-with-transition/3647
裏面已經提出了實現的方法,基本思路就是在爲Director添加一個新的支持使用過渡來彈出場景的函數,帖子中挺長,中間提出了多種實現方式,
有使用模板成員函數來實現的,如下所示:
template<typename T>
void popSceneWithTransition(float t)
{
CCAssert(m_pRunningScene != NULL, "running scene should not null");
m_pobScenesStack->removeLastObject();
unsigned int c = m_pobScenesStack->count();
if (c == 0)
{
end();
}
else
{
m_bSendCleanupToScene = true;
m_pNextScene = (CCScene*)m_pobScenesStack->objectAtIndex(c - 1);
CCScene* trans = T::create(t, m_pNextScene);
//m_pobScenesStack->replaceObjectAtIndex(c-1, (CCScene*)trans);
m_pNextScene = trans;
}
}
以上方法只能支持只需要一個float參數來進行創建的Transition,對於像TransitionPageTurn這樣的Transition就不能支持了
也有人提出爲3.x編寫的使用了C++ 11的function作爲參數,結合lambda表達式的版本。
這裏貼出我個人覺得比較容易理解也是比較靈活好用一個實現方法,需要實現2個函數:
CCScene *previousScene(void)
{
unsigned int c = m_pobScenesStack->count();
if (c <= 1) return NULL;
return (CCScene*)m_pobScenesStack->objectAtIndex(c - 2);
}
void popScene(CCScene *trans)
{
CCAssert(m_pRunningScene != NULL, "running scene should not null");
m_pobScenesStack->removeLastObject();
unsigned int c = m_pobScenesStack->count();
if (c == 0)
{
end();
}
else
{
m_bSendCleanupToScene = true;
m_pNextScene = trans; // (CCScene*)m_pobScenesStack->objectAtIndex(c - 1);
}
}
在Director中實現了以上的2個函數後,在代碼中就可以使用以下的例子代碼來進行帶過渡的popScene了:
CCScene *prevScene = CCDirector::sharedDirector()->previousScene();
CCTransitionScene* transition = CCTransitionPageTurn::create(0.66, prevScene, false);
CCDirector::sharedDirector()->popScene(transition);
以上的方法也可以適用於Cocos2d-x 3.x版本,這裏給出在3.x版本中實現的版本:
Scene * Director::getPreviousScene()
{
unsigned int c = _scenesStack.size();
if (c <= 1) return NULL;
return (Scene*)_scenesStack.at(c - 2);
}
void Director::popSceneWithTransition(Scene * trans)
{
log("popSceneWithTransition+++++++++++++++++++++++++++++++stack size = %d",_scenesStack.size());
CCASSERT(_runningScene != NULL, "running scene should not null");
_scenesStack.popBack();
unsigned int c = _scenesStack.size();
if (c == 0) {
end();
}
else {
_sendCleanupToScene = true;
//以下2句原來是個人認爲應該將彈出當前場景後,將前一個已被包裝在過渡場景中的previuousScene也彈出,然後壓入包裝好的TransitionScene
//後來仔細查看了源碼,發現其實沒有這2句,也是可以正常工作的
//_scenesStack.popBack();
//_scenesStack.pushBack(trans);
_nextScene = trans; // (CCScene*)m_pobScenesStack->objectAtIndex(c - 1);
}
}
目前還不知道有沒有更好的實現方法