基于cocos2d-x 2.1.3开发如下代码:
void LoadScene::onEnter()
{
this->runAction(CCCallFunc::create(this, callfunc_selector(LoadScene::changeScene))));
}
void LoadScene::changeScene()
{
CCDirector::shareDirector()->replaceScene(FightScene::create());
}
发现无论如何运行,清理,都无法按照想法跳转场景FightScene,怀疑n多,修改FightScene,修改changeScene函数调用方式,完全无效,最终怀疑CCCallFunc动作,修改如下:
void LoadScene::onEnter()
{
this->runAction(CCSequence::create(
CCDelayTime::create(.5f),
CCCallFunc::create(this, callfunc_selector(LoadScene::startFight)),
NULL
));
}
顺利跳转。
究其原因,CCNode::onEnter函数,为CCNode加入界面渲染序列时的“事件”。CCScene的onEnter函数会在场景可以“看到”以前就先执行,所以我们也常将之用于场景的一些初始化动作。如果在onEnter中,立即执行了场景转换CCDirector::shareDirector()->replaceScene(),那么,执行场景转换时,当前场景并没有被渲染完成,在replace过后,还会继续执行当前场景的渲染。结果就是,貌似跳转失败。其实,真实的过程是
渲染本场景->跳转->初始化下一场景->继续渲染本场景
原理很简单,但是配合多线程和Action的时候,难免忘记,作此留念
6月6日 更新
如果使用CCTextureCache::sharedTextureCache()->addImageAsync()来进行图片加载,必然加入类似loadImageCallBack(CCObject*)这样的回调来处理图片加载完成的信息,如果在这个回调中直接进行了CCScene的replace,会发现,出现莫名其妙的CCNode::onEnter中resumeAllAction***这样的方法出现报错。
这个就涉及到cocos2d-x的多线程处理了。cocos2d-x的主线程以外的线程一定不能直接或间接触碰OpenGL的内容。偏偏CCTextureCache::sharedTextureCache()->addImageAsync()就是使用子线程加载图片,达到主线程可以查看加载动态加载进度的要求。(同理,如果其他数据内容需要进行加载,也可以自己写个pthread来加载,然后在主线程中显示进度,这部分内容另说)。所以,一定不能在CCTextureCache::sharedTextureCache()->addImageAsync()的回调或者这个回调函数调用到的其他函数中,进行replaceScene一类的OpenGl相关的API。
解决方法,感觉没有什么好的方法,目前只能是在主线程中加入标识变量,然后主线程中使用schedule进行轮询,再处理。
另,使用CCTextureCache::sharedTextureCache()->addImageAsync()加载,在需要加载的图片全部都已经在内存中时,会出现场景无法跳转的问题,原因见楼上。