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


目前还不知道有没有更好的实现方法



你可能感兴趣的:(游戏,Cocos2d-x,OpenGL游戏开发,移动软件开发)