Cocos2d-x中的那些坑-- popScene 不能使用TransitionScene的一種解決方法

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);
	}
}


目前還不知道有沒有更好的實現方法微笑



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章