您的位置:首页 > 移动开发 > Cocos引擎

Cocos2d-x学习笔记(八)场景切换原理分析

2014-08-26 16:51 603 查看
原创文章,转载请注明出处:http://blog.csdn.net/sfh366958228/article/details/38845319

前言

终于讲完了CCAction的实现原理,现在有理论基础来说场景切换的原理了,其实不难猜到很多的场景切换效果十通过CCAction来实现的。

CCDirector::sharedDirector()->replaceScene(CCTransitionRotoZoom::create(2.0f, MenuScene::scene()));
这是一个基本的场景切换代码,那么就让我们从replaceScene开始看起吧~

CCDirector::replaceScene

void CCDirector::replaceScene(CCScene *pScene)
{
CCAssert(m_pRunningScene, "Use runWithScene: instead to start the director"); //判断是否有正在运行的场景,没有的话应以runWithScene代替replaceScene
CCAssert(pScene != NULL, "the scene should not be null"); // 确保待切换场景不为空
unsigned int index = m_pobScenesStack->count(); // 获取场景栈中场景数量
m_bSendCleanupToScene = true; // 将清空场景标记为true
m_pobScenesStack->replaceObjectAtIndex(index - 1, pScene); // 将场景放在容器结尾
m_pNextScene = pScene; // 将下一个场景设置为pScene
}
看到这时有点懵,感觉没法往下走了,寻寻觅觅,终于还是发现了结果。答案就在主循环中mainLoop,我们会调用设备的drawScene方法。

CCDirector::drawScene

void CCDirector::drawScene(void)
{
calculateDeltaTime(); // 计算帧间隔时间
if (! m_bPaused) // Director是否暂停
{
m_pScheduler->update(m_fDeltaTime); // 更新毁掉函数管理器
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // OPENGL清除后台缓冲区的颜色和深度,这是每一帧OPENGL进行渲染前要做的处理。
if (m_pNextScene)
{
setNextScene(); // 如果有新的场景要设置,调用setNextScene函数进行相关处理。
}
...
}

不难发现,关键应该在setNextScene这个方法之中。

CCDirector::setNextScene

void CCDirector::setNextScene(void)
{
bool runningIsTransition = dynamic_cast<CCTransitionScene*>(m_pRunningScene) != NULL; // 定义bool变量runningIsTransition,判断当前运行中的场景是否是切换场景类,如果是,将runningIsTransition设为true
bool newIsTransition = dynamic_cast<CCTransitionScene*>(m_pNextScene) != NULL; // 定义bool变量newIsTransition,判断要设置的新场景是否是切换场景类,如果是,将newIsTransition设为true

if (! newIsTransition)
{ // 如果新场景不是切换场景类而是一个普通场景
if (m_pRunningScene)
{ // 如果m_pRunningScene不为空,则调用对应场景结束方法
m_pRunningScene->onExitTransitionDidStart();
m_pRunningScene->onExit();
}

// 如果m_bSendCleanupToScene标记为true且有正在运行的场景则调用它的cleanup函数
if (m_bSendCleanupToScene && m_pRunningScene)
{
m_pRunningScene->cleanup();
}
}

if (m_pRunningScene)
{ // 调用当前正在运行的场景的释放函数
m_pRunningScene->release();
}
m_pRunningScene = m_pNextScene; // 将新场景置为当前场景
m_pNextScene->retain(); //新场景计数加1
m_pNextScene = NULL; // 新场景指针置为空

if ((! runningIsTransition) && m_pRunningScene)
{ // 调用新场景的onEnter函数
m_pRunningScene->onEnter();
m_pRunningScene->onEnterTransitionDidFinish();
}
}


CCTransitionRotoZoom::onEnter

讲到这,我们已经大概了解了场景切换的步骤,最后的切换动作实现,还是落在了场景切换类自身的实现上。

void CCTransitionRotoZoom::onEnter()
{
// 调用基类的相应函数
CCTransitionScene::onEnter();
// 设置新场景的初始缩放值为0.001,缩小了100倍
m_pInScene->setScale(0.001f);
// 设置原场景的初始缩放值为原大小
m_pOutScene->setScale(1.0f);
// 设置场景的锚点做为旋转缩放中心
m_pInScene->setAnchorPoint(ccp(0.5f, 0.5f));
m_pOutScene->setAnchorPoint(ccp(0.5f, 0.5f));
//创建一个序列动画
CCActionInterval *rotozoom = (CCActionInterval*)(CCSequence::create(CCSpawn::create // 这个序列动画有两部分,第一部分是一个组合动画,这个组合动画由缩放和旋转组合而成
(CCScaleBy::create(m_fDuration/2, 0.001f), // 一半动画时间内从当前缩放值缩小100倍
CCRotateBy::create(m_fDuration/2, 360 * 2), // 一半动画时间内从当前旋转状态旋转两圈
NULL),
CCDelayTime::create(m_fDuration/2), // 序列动画的第二部分是一个暂停一半动画时间的暂停动画
NULL));
// 对原场景运行上面创建的序列动画,让它在一半动画时长内旋转2圈,并由原大小缩小100倍,然后暂停一半动画时长
m_pOutScene->runAction(rotozoom);
// 对新的场景运行另一个序列动画
m_pInScene->runAction(CCSequence::create(// 这个序列动画也有两部分构成,第一部分是上面序列动画的反向动画,第二部分是调用finish函数
rotozoom->reverse(),
CCCallFunc::create(this, callfunc_selector(CCTransitionScene::finish)),
NULL));
}


结语

看到这,我们最初的想法也基本得到证明,在不过和语气有点不一样得是,replaceScene之后,场景并没有直接切换,而是等到主线程的步骤中再继续,这两天对Action和场景切换的原理进行了简单讲解,有没有对原理性的东西更加感兴趣呢?

参考资料

Cocos2d-x 2.0 TestCpp之场景切换动画深入分析:/article/1667882.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: