No.1 CCScene(场景)

 

当你用CCDirector::replaceScene(CCScene *pScene)方法替换场景时,每个节点都会调用CCNode所带的三个方法.

这三个方法如下所示:

 
  
  1. /*-----------CCTransitionScene为场景切换方式--------------*/ 
  2.     // 节点调用init方法以后将会调用此方法 
  3.     // 如果使用了CCTransitionScene,将会在过渡效果开始以后调用此方法 
  4.     virtual void onEnter(); 
  5.  
  6.     // 调用onEnter以后将会调用此方法 
  7.     // 如果使用了CCTransitionScene,将会在过渡效果结束以后调用此方法 
  8.     virtual void onEnterTransitionDidFinish(); 
  9.  
  10.     // 节点调用dealloc方法之前将会调用此方法 
  11.     // 如果使用了CCTransitionScene,将会在过渡效果结束以后调用此方法 
  12.     virtual void onExit(); 

 -----------------请详细查看下面文字-------------------

 
  
  1. /*
  2. 如果你不在onEnter方法里调用它的super方法的话,
  3. 你的新场景可能不会对触摸或者加速计的输入有任何反应。
  4.  
  5. 如果你不在onExit方法里调用它的super方法,当前场景可能不会从内存里释放。
  6.  
  7. 因为很容易忘记添加super方法,而且在发生问题以后也很难与没有调用super方法联系起来,
  8. 我要在这里特别强调这一点。
  9. */ 
 
  
  1. /* 
  2. 在程序进入onEnter()方法的时候,场景中所有节点都已经设置完成了 
  3. 同时,在onExit()方法中,所有节点都还存在于内存中 
  4. */ 

----------------两个CCScene切换时调用方法的顺序---------------

 
  
  1. scene() //CCScene2的方法   
  2. ↓   
  3. init() //CCScene2的方法  
  4. ↓   
  5. onEnter() //CCScene2的方法   
  6. ↓   
  7. 过渡效果   
  8. ↓   
  9. onExit() //CCScene1的方法  
  10. ↓   
  11. onEnterTransitionDidFinish() //CCScene2的方法  
  12. ↓   
  13. dealloc //CCScene1的方法 

 你会注意到 CCScene1中的dealloc方法是最后一个调用的 ,那就意味着onEnterTransitionDidFinish方法运行的时候,之前的场景还是在内存中。

如果你想在onEnterTransitionDidFinish中分配很耗内存的节点,你必须先预约一个方法或者选择器(selector),至少等到下一桢的时候才分配内存,这样可以确保之前的场景已经从内存中释放出来

 


 过渡场景の正在加载页面

当你加入的东西越来越多的时候,场景切换的时间也会越来越长,其实场景的生成早于场景的过渡效果
所以。

如果需要在新场景的init或者Enter方法中添加较复杂的代码或者加载较多的素材的时候,就可以明显感到过渡效果的开始之前就会产生明显的延迟。

切换场景的时间超过1s的时候,用户就会觉得游戏卡住了,会大大的降低用户的好感。这个问题应该怎么解决呢?--------->在两个场景切换的时候添加一个过渡场景

Now  我们来新建一个场景类LoadingScene,它继承于CCScene类

你没有必要为每个过渡效果创建一个新的LoadingScene类,你可以通过指定需要加载的场景类来调用相同的LoadingScene场景, so  枚举类型很适合我们的需求

LoadingScene.h的代码

 
  
  1. #ifndef LOADINGSCENE_H 
  2. #define LOADINGSCENE_H 
  3.  
  4. typedef enum 
  5.   TargetSceneINVALID = 0, 
  6.   TargetSceneFirstScene, 
  7.   TargetSceneOtherScene, 
  8.   TargetSceneMAX 
  9. } TargetScenes; 
  10.  
  11. #include "cocos2d.h" 
  12. USING_NS_CC; 
  13. //LoadingScene直接继承自CCScene,在这个场景中我们不需要CCLayer 
  14. class LoadingScene: public CCScene { 
  15. public
  16.   LoadingScene(); 
  17.   static LoadingScene* sceneWithTargetScene(TargetScenes targetScene); 
  18. private
  19.   virtual void update(ccTime dt); 
  20.   bool initWithTargetScene(TargetScenes targetScene); 
  21.   TargetScenes targetScene_; 
  22. }; 
  23.  
  24. #endif // LOADINGSCENE_H  

 将枚举类型的第一个值设置为INVALID值是个好习惯,除非你想把第一个元素设为默认的。除非你指定一个不同的值,Objective-C的变量会被自动初始为0

在LoadingScene里面我们MAX或者NUM,但是有时候我加上它们是出于习惯,即使我们不需要使用他们。

 注:为什么我们不在init方法里直接使用replaceScene方法呢?这里有两条规则需要遵守。规则一:永远不要在一个节点的init方法中调用CCDirector的replaceScene方法。规则二:请遵守规则一。不遵守规则的后果是程序崩溃。Director无法容忍一个节点在初始化的同时进行场景替换。

 下面为LoadingScene.cpp代码:

 

 
  
  1. #include "LoadingScene.h" 
  2. #include "FirstScene.h" 
  3. #include "OtherScene.h" 
  4.  
  5. LoadingScene::LoadingScene() { 
  6.  
  7.  
  8. LoadingScene *LoadingScene::sceneWithTargetScene(TargetScenes targetScene) { 
  9.     // 以下代码生成了一个当前类的自动释放对象 
  10.     LoadingScene *aLoadingScene = new LoadingScene(); 
  11.     aLoadingScene->initWithTargetScene(targetScene); 
  12.     aLoadingScene->autorelease(); 
  13.     return aLoadingScene; 
  14.  
  15. bool LoadingScene::initWithTargetScene(TargetScenes targetScene) { 
  16.     if (CCScene::init()) { 
  17.         targetScene_ = targetScene; 
  18.         //创建一个Label标签放在屏幕中央 
  19.         CCLabelTTF* label = CCLabelTTF::labelWithString("Loading ..."
  20.                 "fonts/Marker Felt.ttf", 64); 
  21.         CCSize size = CCDirector::sharedDirector()->getWinSize(); 
  22.         label->setPosition(ccp(size.width / 2, size.height / 2)); 
  23.         this->addChild(label); 
  24.         // 必须在下一帧才加载目标场景! 
  25.         this->scheduleUpdate(); 
  26.         return true
  27.     } 
  28.  
  29.     return false
  30.  
  31. void LoadingScene::update(ccTime delta) { 
  32.     //终止所有的预定信息 
  33.     this->unscheduleAllSelectors(); 
  34.     // 通过TargetScenes这个枚举类型来决定加载哪个场景 
  35.     switch (targetScene_) { 
  36.     case TargetSceneFirstScene: 
  37.         CCDirector::sharedDirector()->replaceScene(FirstScene::scene()); 
  38.         break
  39.     case TargetSceneOtherScene: 
  40.         CCDirector::sharedDirector()->replaceScene(OtherScene::scene()); 
  41.         break
  42.     default
  43.         // 如果使用了没有指定的枚举类型,发出警告信息 
  44.         CCAssert( "不存在的目标场景 %d", targetScene_); 
  45.         break
  46.     } 
  47.     for (TargetScenes i = TargetSceneINVALID + 1; i < TargetSceneMAX; i++) { 
  48.     } 

至此,完成LoadingScene场景的开发

接下来讲解如何去使用这个LoadingScene场景类,

先来看下FirstScene场景的代码:

 FirstScene.h

 

 
  
  1. /* 
  2.  * FirstScene.h 
  3.  * 
  4.  *  Created on: 2012-9-10 
  5.  *      Author: Panda 
  6.  */ 
  7.  
  8. #ifndef FirstScene_H_ 
  9. #define FirstScene_H_ 
  10. #include "cocos2d.h" 
  11.  
  12. USING_NS_CC; 
  13. class FirstScene: public CCLayer { 
  14.  
  15. public
  16.     FirstScene(); 
  17.     virtual ~FirstScene(); 
  18.  
  19.     virtual bool init(void); 
  20.     static CCScene *scene(); 
  21.     void Torment(); 
  22.     virtual void ccTouchesEnded(CCSet *pTouches,CCEvent *pEvent); 
  23.     CREATE_FUNC(FirstScene) 
  24.     ; 
  25. }; 
  26. #endif /* FirstScene_H_ */ 

FirstScene.cpp

 

 
  
  1. /* 
  2.  * FirstScene.cpp 
  3.  * 
  4.  *  Created on: 2012-9-10 
  5.  *      Author: Panda 
  6.  */ 
  7.  
  8. #include "FirstScene.h" 
  9. #include "OtherScene.h" 
  10. #include "LoadingScene.h" 
  11.  
  12. FirstScene::FirstScene() { 
  13.     // TODO Auto-generated constructor stub 
  14.  
  15.  
  16. FirstScene::~FirstScene() { 
  17.     // TODO Auto-generated destructor stub 
  18.  
  19. bool FirstScene::init() { 
  20.     bool bRet = false
  21.     do { 
  22.  
  23.         CCSize winSize = CCDirector::sharedDirector()->getWinSize(); 
  24.         CC_BREAK_IF(!CCLayer::init()); 
  25.  
  26.         CCLabelTTF *label = CCLabelTTF::create("触摸屏幕进入下一个场景"
  27.                 "Arial.fnt", 60); 
  28.         label->setPosition(ccp(winSize.width/2,winSize.height/2)); 
  29.         this->addChild(label); 
  30.  
  31.         this->Torment(); 
  32.         this->setTouchEnabled(true); 
  33.         bRet = true
  34.     } while (0); 
  35.     return bRet; 
  36.  
  37. CCScene *FirstScene::scene() { 
  38.     CCScene *pScene = NULL; 
  39.     do { 
  40.         pScene = CCScene::create(); 
  41.         CC_BREAK_IF(!pScene); 
  42.         FirstScene *helloworld = FirstScene::create(); 
  43.         CC_BREAK_IF(!helloworld); 
  44.         pScene->addChild(helloworld); 
  45.     } while (0); 
  46.     return pScene; 
  47.  
  48. void FirstScene::ccTouchesEnded(CCSet *pTouch, CCEvent *pEvent) { 
  49.     CCDirector::sharedDirector()->replaceScene(LoadingScene::sceneWithTargetScene(TargetSceneOtherScene)); 
  50.  
  51. void FirstScene::Torment() { 
  52. //模擬耗时操作 
  53.     float a = 2423; 
  54.     float b = 3432; 
  55.     for (int i = 0; i < 300000000; i++) { 
  56.         a /= b; 
  57.     } 

没啥疑问   主要是在切换到第二个界面的时候需要调用LoadingScene::sceneWithTargetScene(TargetSceneOtherScene)

 

再来看看OtherScene场景的代码:

OtherScene.h

 

 
  
  1. /* 
  2.  * OtherScene.h 
  3.  * 
  4.  *  Created on: 2012-9-12 
  5.  *      Author: Panda 
  6.  */ 
  7.  
  8. #ifndef OTHERSCENE_H_ 
  9. #define OTHERSCENE_H_ 
  10.  
  11. #include "cocos2d.h" 
  12. USING_NS_CC; 
  13.  
  14. class OtherScene :CCLayer{ 
  15. public
  16.     OtherScene(); 
  17.     virtual ~OtherScene(); 
  18.  
  19.     virtual bool init(); 
  20.     static CCScene *scene(); 
  21.     void Torment(); 
  22.     CREATE_FUNC(OtherScene); 
  23. }; 
  24.  
  25. #endif /* OTHERSCENE_H_ */ 

OtherScene.cpp

 
  
  1. /* 
  2.  * OtherScene.cpp 
  3.  * 
  4.  *  Created on: 2012-9-12 
  5.  *      Author: Panda 
  6.  */ 
  7.  
  8. #include "OtherScene.h" 
  9. #include "FirstScene.h" 
  10. #include "LoadingScene.h" 
  11.  
  12. OtherScene::OtherScene() { 
  13.     // TODO Auto-generated constructor stub 
  14.  
  15.  
  16. OtherScene::~OtherScene() { 
  17.     // TODO Auto-generated destructor stub 
  18.  
  19. bool OtherScene::init() { 
  20.     bool bRet = false
  21.     do { 
  22.         CCSize winSize = CCDirector::sharedDirector()->getWinSize(); 
  23.         CC_BREAK_IF(!CCLayer::init()); 
  24.  
  25.         CCLabelTTF *label = CCLabelTTF::create("OtherScene场景""Arial.fnt", 30); 
  26.         label->setPosition(ccp(winSize.width/2,winSize.height/2)); 
  27.         this->addChild(label); 
  28.  
  29.         this->Torment(); 
  30.         bRet = true
  31.     } while (0); 
  32.     return bRet; 
  33.  
  34. CCScene *OtherScene::scene() { 
  35.     CCScene *pScene = NULL; 
  36.     do { 
  37.         pScene = CCScene::create(); 
  38.         CC_BREAK_IF(!pScene); 
  39.         OtherScene *helloworld = OtherScene::create(); 
  40.         CC_BREAK_IF(!helloworld); 
  41.         pScene->addChild(helloworld); 
  42.     } while (0); 
  43.     return pScene; 
  44.  
  45. void OtherScene::Torment() { 
  46.     //模擬耗时操作 
  47.     float a = 2423; 
  48.     float b = 3432; 
  49.     for (int i = 0; i < 300000000; i++) { 
  50.         a /= b; 
  51.     } 

 


接下来一章将讲解如何使用多个层,如有问题,请提出

本教程根据Cocos2d教程翻译过来