首页 > 代码库 > Cocos2d-x学习笔记(八)场景切换原理分析

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

原创文章,转载请注明出处: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之场景切换动画深入分析:http://blog.csdn.net/honghaier/article/details/8475341

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