虽然coco2d-x里提供了很多强大的场景转换类 ,但有时候自己需要的一些效果cocos2d-x还是无法解决,毕竟越是方便的东西越有它的局限性,所以我就自己定义了一个场景转换类:
因为自定义的场景转换类 需要继承 CCTransitionScene场景转换基类,于是我还是把场景转换类的代码 全部看了一遍,以防在某些环节使用不当而导致未知的错误,所以我先来说明CCTransitionScene 的内部构造和实现方式。
首先,我们来看看 CCTransitionScene的定义
class CC_DLL CCTransitionScene : public CCScene
{
protected:
//载入场景
CCScene * m_pInScene;
//载出场景
CCScene * m_pOutScene;
//动画播放时间
float m_fDuration;
//顾名思义 就是载入场景是否置顶
bool m_bIsInSceneOnTop;
//载出场景是否需要被清理,在clearnup()中被调用
bool m_bIsSendCleanupToScene;
public:
CCTransitionScene();
virtual ~CCTransitionScene();
//决定场景 层的先后顺序
virtual void draw();
virtual void onEnter();
virtual void onExit();
//清理载出场景
virtual void cleanup();
/** creates a base transition with duration and incoming scene
@deprecated: This interface will be deprecated sooner or later.
*/
//CC_DEPRECATED_ATTRIBUTE 表示 不建议使用的,分配空间函数
CC_DEPRECATED_ATTRIBUTE static CCTransitionScene * transitionWithDuration(float t, CCScene *scene);
/** creates a base transition with duration and incoming scene */
//同上,现在cocos2d-x把地址分配函数都 统一成create ,这点做的很好
static CCTransitionScene * create(float t, CCScene *scene);
/** initializes a transition with duration and incoming scene */
//初始化函数,一般不需要自己调用
virtual bool initWithDuration(float t,CCScene* scene);
/** called after the transition finishes */
//销毁函数,当新场景载入完成时隐式销毁旧场景
void finish(void);
/** used by some transitions to hide the outer scene */
//隐藏旧场景 显示新场景
void hideOutShowIn(void);
protected:
//把载入场景置顶
virtual void sceneOrder();
private:
void setNewScene(float dt);
};
看看各个函数的定义
CCTransitionScene * CCTransitionScene::create(float t, CCScene *scene)
{
CCTransitionScene * pScene = new CCTransitionScene();//分配地址
if(pScene && pScene->initWithDuration(t,scene))//初始化
{
//用smart point
pScene->autorelease();
return pScene;
}
//安全释放,既if(pScene)delete pScene = 0
CC_SAFE_DELETE(pScene);
return NULL;
}
transitionWithDuration 函数也是调用create
bool CCTransitionScene::initWithDuration(float t, CCScene *scene)
{
CCAssert( scene != NULL, "Argument scene must be non-nil");
if (CCScene::init())
{
m_fDuration = t;
// retain
m_pInScene = scene;
m_pInScene->retain();
m_pOutScene = CCDirector::sharedDirector()->getRunningScene(); if (m_pOutScene == NULL) { m_pOutScene = CCScene::create(); m_pOutScene->init(); } m_pOutScene->retain(); //防止 旧场景 和新场景是 同一场景 CCAssert( m_pInScene != m_pOutScene, "Incoming scene must be different from the outgoing scene" ); // disable events while transitions//保证2个场景同时存在
CCDirector* pDirector = CCDirector::sharedDirector();
pDirector->getTouchDispatcher()->setDispatchEvents(false);//停止 所有touch 事件
让新场景置顶 this->sceneOrder(); return true; } else { return false; } }
void CCTransitionScene::sceneOrder() { m_bIsInSceneOnTop = true; } void CCTransitionScene::draw() { CCScene::draw(); //画场景的先后顺序 if( m_bIsInSceneOnTop ) { m_pOutScene->visit(); m_pInScene->visit(); } else { m_pInScene->visit(); m_pOutScene->visit(); } } void CCTransitionScene::finish() { // clean up
//场景转换完成,还原所有场景 然后delete 掉旧场景 replace 到新场景 m_pInScene->setVisible(true); m_pInScene->setPosition(ccp(0,0)); m_pInScene->setScale(1.0f); m_pInScene->setRotation(0.0f); m_pInScene->getCamera()->restore(); m_pOutScene->setVisible(false); m_pOutScene->setPosition(ccp(0,0)); m_pOutScene->setScale(1.0f); m_pOutScene->setRotation(0.0f); m_pOutScene->getCamera()->restore(); //[self schedule:@selector(setNewScene:) interval:0];
还有cocos2d 2.0 的新派生类CCTransitionScene,但今天就写怎么多,下次继续写this->schedule(schedule_selector(CCTransitionScene::setNewScene), 0); } void CCTransitionScene::setNewScene(float dt) { CC_UNUSED_PARAM(dt); // [self unschedule:_cmd]; // "_cmd" is a local variable automatically defined in a method // that contains the selector for the method this->unschedule(schedule_selector(CCTransitionScene::setNewScene)); CCDirector *director = CCDirector::sharedDirector(); // Before replacing, save the "send cleanup to scene" m_bIsSendCleanupToScene = director->isSendCleanupToScene(); director->replaceScene(m_pInScene); // enable events while transitions(恢复touch事件) director->getTouchDispatcher()->setDispatchEvents(true); // issue #267 m_pOutScene->setVisible(true); } void CCTransitionScene::hideOutShowIn() { m_pInScene->setVisible(true); m_pOutScene->setVisible(false); } // custom onEnter void CCTransitionScene::onEnter() { CCScene::onEnter(); m_pInScene->onEnter(); // outScene should not receive the onEnter callback } // custom onExit void CCTransitionScene::onExit() { CCScene::onExit(); m_pOutScene->onExit(); // inScene should not receive the onExit callback // only the onEnterTransitionDidFinish m_pInScene->onEnterTransitionDidFinish(); } // custom cleanup void CCTransitionScene::cleanup() { CCScene::cleanup(); if( m_bIsSendCleanupToScene ) m_pOutScene->cleanup(); }