当你用CCDirector::replaceScene(CCScene *pScene)方法替换场景时,每个节点都会调用CCNode所带的三个方法.
这三个方法如下所示:
- /*-----------CCTransitionScene为场景切换方式--------------*/
- // 节点调用init方法以后将会调用此方法
- // 如果使用了CCTransitionScene,将会在过渡效果开始以后调用此方法
- virtual void onEnter();
- // 调用onEnter以后将会调用此方法
- // 如果使用了CCTransitionScene,将会在过渡效果结束以后调用此方法
- virtual void onEnterTransitionDidFinish();
- // 节点调用dealloc方法之前将会调用此方法
- // 如果使用了CCTransitionScene,将会在过渡效果结束以后调用此方法
- virtual void onExit();
-----------------请详细查看下面文字-------------------
- /*
- 如果你不在onEnter方法里调用它的super方法的话,
- 你的新场景可能不会对触摸或者加速计的输入有任何反应。
- 如果你不在onExit方法里调用它的super方法,当前场景可能不会从内存里释放。
- 因为很容易忘记添加super方法,而且在发生问题以后也很难与没有调用super方法联系起来,
- 我要在这里特别强调这一点。
- */
- /*
- 在程序进入onEnter()方法的时候,场景中所有节点都已经设置完成了
- 同时,在onExit()方法中,所有节点都还存在于内存中
- */
----------------两个CCScene切换时调用方法的顺序---------------
- scene() //CCScene2的方法
- ↓
- init() //CCScene2的方法
- ↓
- onEnter() //CCScene2的方法
- ↓
- 过渡效果
- ↓
- onExit() //CCScene1的方法
- ↓
- onEnterTransitionDidFinish() //CCScene2的方法
- ↓
- dealloc //CCScene1的方法
你会注意到 CCScene1中的dealloc方法是最后一个调用的 ,那就意味着onEnterTransitionDidFinish方法运行的时候,之前的场景还是在内存中。 如果你想在onEnterTransitionDidFinish中分配很耗内存的节点,你必须先预约一个方法或者选择器(selector),至少等到下一桢的时候才分配内存,这样可以确保之前的场景已经从内存中释放出来 |
当你加入的东西越来越多的时候,场景切换的时间也会越来越长,其实场景的生成早于场景的过渡效果 如果需要在新场景的init或者Enter方法中添加较复杂的代码或者加载较多的素材的时候,就可以明显感到过渡效果的开始之前就会产生明显的延迟。 切换场景的时间超过1s的时候,用户就会觉得游戏卡住了,会大大的降低用户的好感。这个问题应该怎么解决呢?--------->在两个场景切换的时候添加一个过渡场景 |
Now 我们来新建一个场景类LoadingScene,它继承于CCScene类
你没有必要为每个过渡效果创建一个新的LoadingScene类,你可以通过指定需要加载的场景类来调用相同的LoadingScene场景, so 枚举类型很适合我们的需求
LoadingScene.h的代码:
- #ifndef LOADINGSCENE_H
- #define LOADINGSCENE_H
- typedef enum
- {
- TargetSceneINVALID = 0,
- TargetSceneFirstScene,
- TargetSceneOtherScene,
- TargetSceneMAX
- } TargetScenes;
- #include "cocos2d.h"
- USING_NS_CC;
- //LoadingScene直接继承自CCScene,在这个场景中我们不需要CCLayer
- class LoadingScene: public CCScene {
- public:
- LoadingScene();
- static LoadingScene* sceneWithTargetScene(TargetScenes targetScene);
- private:
- virtual void update(ccTime dt);
- bool initWithTargetScene(TargetScenes targetScene);
- TargetScenes targetScene_;
- };
- #endif // LOADINGSCENE_H
将枚举类型的第一个值设置为INVALID值是个好习惯,除非你想把第一个元素设为默认的。除非你指定一个不同的值,Objective-C的变量会被自动初始为0 在LoadingScene里面我们MAX或者NUM,但是有时候我加上它们是出于习惯,即使我们不需要使用他们。 |
注:为什么我们不在init方法里直接使用replaceScene方法呢?这里有两条规则需要遵守。规则一:永远不要在一个节点的init方法中调用CCDirector的replaceScene方法。规则二:请遵守规则一。不遵守规则的后果是程序崩溃。Director无法容忍一个节点在初始化的同时进行场景替换。 |
下面为LoadingScene.cpp代码:
- #include "LoadingScene.h"
- #include "FirstScene.h"
- #include "OtherScene.h"
- LoadingScene::LoadingScene() {
- }
- LoadingScene *LoadingScene::sceneWithTargetScene(TargetScenes targetScene) {
- // 以下代码生成了一个当前类的自动释放对象
- LoadingScene *aLoadingScene = new LoadingScene();
- aLoadingScene->initWithTargetScene(targetScene);
- aLoadingScene->autorelease();
- return aLoadingScene;
- }
- bool LoadingScene::initWithTargetScene(TargetScenes targetScene) {
- if (CCScene::init()) {
- targetScene_ = targetScene;
- //创建一个Label标签放在屏幕中央
- CCLabelTTF* label = CCLabelTTF::labelWithString("Loading ...",
- "fonts/Marker Felt.ttf", 64);
- CCSize size = CCDirector::sharedDirector()->getWinSize();
- label->setPosition(ccp(size.width / 2, size.height / 2));
- this->addChild(label);
- // 必须在下一帧才加载目标场景!
- this->scheduleUpdate();
- return true;
- }
- return false;
- }
- void LoadingScene::update(ccTime delta) {
- //终止所有的预定信息
- this->unscheduleAllSelectors();
- // 通过TargetScenes这个枚举类型来决定加载哪个场景
- switch (targetScene_) {
- case TargetSceneFirstScene:
- CCDirector::sharedDirector()->replaceScene(FirstScene::scene());
- break;
- case TargetSceneOtherScene:
- CCDirector::sharedDirector()->replaceScene(OtherScene::scene());
- break;
- default:
- // 如果使用了没有指定的枚举类型,发出警告信息
- CCAssert( "不存在的目标场景 %d", targetScene_);
- break;
- }
- for (TargetScenes i = TargetSceneINVALID + 1; i < TargetSceneMAX; i++) {
- }
- }
至此,完成LoadingScene场景的开发
接下来讲解如何去使用这个LoadingScene场景类,
先来看下FirstScene场景的代码:
FirstScene.h
- /*
- * FirstScene.h
- *
- * Created on: 2012-9-10
- * Author: Panda
- */
- #ifndef FirstScene_H_
- #define FirstScene_H_
- #include "cocos2d.h"
- USING_NS_CC;
- class FirstScene: public CCLayer {
- public:
- FirstScene();
- virtual ~FirstScene();
- virtual bool init(void);
- static CCScene *scene();
- void Torment();
- virtual void ccTouchesEnded(CCSet *pTouches,CCEvent *pEvent);
- CREATE_FUNC(FirstScene)
- ;
- };
- #endif /* FirstScene_H_ */
FirstScene.cpp
- /*
- * FirstScene.cpp
- *
- * Created on: 2012-9-10
- * Author: Panda
- */
- #include "FirstScene.h"
- #include "OtherScene.h"
- #include "LoadingScene.h"
- FirstScene::FirstScene() {
- // TODO Auto-generated constructor stub
- }
- FirstScene::~FirstScene() {
- // TODO Auto-generated destructor stub
- }
- bool FirstScene::init() {
- bool bRet = false;
- do {
- CCSize winSize = CCDirector::sharedDirector()->getWinSize();
- CC_BREAK_IF(!CCLayer::init());
- CCLabelTTF *label = CCLabelTTF::create("触摸屏幕进入下一个场景",
- "Arial.fnt", 60);
- label->setPosition(ccp(winSize.width/2,winSize.height/2));
- this->addChild(label);
- this->Torment();
- this->setTouchEnabled(true);
- bRet = true;
- } while (0);
- return bRet;
- }
- CCScene *FirstScene::scene() {
- CCScene *pScene = NULL;
- do {
- pScene = CCScene::create();
- CC_BREAK_IF(!pScene);
- FirstScene *helloworld = FirstScene::create();
- CC_BREAK_IF(!helloworld);
- pScene->addChild(helloworld);
- } while (0);
- return pScene;
- }
- void FirstScene::ccTouchesEnded(CCSet *pTouch, CCEvent *pEvent) {
- CCDirector::sharedDirector()->replaceScene(LoadingScene::sceneWithTargetScene(TargetSceneOtherScene));
- }
- void FirstScene::Torment() {
- //模�M耗时操作
- float a = 2423;
- float b = 3432;
- for (int i = 0; i < 300000000; i++) {
- a /= b;
- }
- }
没啥疑问 主要是在切换到第二个界面的时候需要调用LoadingScene::sceneWithTargetScene(TargetSceneOtherScene)
再来看看OtherScene场景的代码:
OtherScene.h
- /*
- * OtherScene.h
- *
- * Created on: 2012-9-12
- * Author: Panda
- */
- #ifndef OTHERSCENE_H_
- #define OTHERSCENE_H_
- #include "cocos2d.h"
- USING_NS_CC;
- class OtherScene :CCLayer{
- public:
- OtherScene();
- virtual ~OtherScene();
- virtual bool init();
- static CCScene *scene();
- void Torment();
- CREATE_FUNC(OtherScene);
- };
- #endif /* OTHERSCENE_H_ */
OtherScene.cpp
- /*
- * OtherScene.cpp
- *
- * Created on: 2012-9-12
- * Author: Panda
- */
- #include "OtherScene.h"
- #include "FirstScene.h"
- #include "LoadingScene.h"
- OtherScene::OtherScene() {
- // TODO Auto-generated constructor stub
- }
- OtherScene::~OtherScene() {
- // TODO Auto-generated destructor stub
- }
- bool OtherScene::init() {
- bool bRet = false;
- do {
- CCSize winSize = CCDirector::sharedDirector()->getWinSize();
- CC_BREAK_IF(!CCLayer::init());
- CCLabelTTF *label = CCLabelTTF::create("OtherScene场景", "Arial.fnt", 30);
- label->setPosition(ccp(winSize.width/2,winSize.height/2));
- this->addChild(label);
- this->Torment();
- bRet = true;
- } while (0);
- return bRet;
- }
- CCScene *OtherScene::scene() {
- CCScene *pScene = NULL;
- do {
- pScene = CCScene::create();
- CC_BREAK_IF(!pScene);
- OtherScene *helloworld = OtherScene::create();
- CC_BREAK_IF(!helloworld);
- pScene->addChild(helloworld);
- } while (0);
- return pScene;
- }
- void OtherScene::Torment() {
- //模�M耗时操作
- float a = 2423;
- float b = 3432;
- for (int i = 0; i < 300000000; i++) {
- a /= b;
- }
- }
接下来一章将讲解如何使用多个层,如有问题,请提出
本教程根据Cocos2d教程翻译过来