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

来源:互联网 发布:安卓系统数据网络开关 编辑:程序博客网 时间:2024/04/29 08:27

原创文章,转载请注明出处: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

0 0
原创粉丝点击