前言:

一个场景(Scene)是由多个层(Layer)组成,而且层的个数要至少是1,不能为0。

场景切换

场景切换相关函数

1)void  runWithScene(Scene*  scene)

该函数可以运行场景。只能在启动第一个场景时调用该函数。如果已经有一个场景运行,则不能调用该函数。

2)void  replaceScene(Scene*  scene)

切换到下一个场景。用一个新的场景替换当前场景,当前场景被终端释放

3)void  pushScene(Scene*  scene)

切换到下一个场景。将当前场景挂起放入到场景堆栈中,然后再切换到下一个场景中。

4)void  popScene(Scene*  scene)

与 pushScene 配合使用,可以回到上一个场景。

5)void  popToRootScene(Scene*  scene)

与 pushScene 配合使用,可以回到根场景。

代码示例:

 #ifndef __HELLOWORLD_SCENE_H__
 #define __HELLOWORLD_SCENE_H__

 #include "cocos2d.h"
 #include "Setting.h"

 class HelloWorld : public cocos2d::Layer
 {
 public:
     // there's no 'id' in cpp, so we recommend returning the class instance pointer
     static cocos2d::Scene* createScene();

     // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
     virtual bool init();  

     // a selector callback
     void menuCloseCallback(cocos2d::Ref* pSender);

     ////
     void menuItemStartCallback(Ref* pSender);
     void menuItemSettingCallback(Ref* pSender);
     void menuItemHelpCallback(Ref* pSender);

     // implement the "static create()" method manually
     CREATE_FUNC(HelloWorld);
 };

 #endif // __HELLOWORLD_SCENE_H__
 #include "HelloWorldScene.h"

 USING_NS_CC;

 Scene* HelloWorld::createScene()
 {
     // 'scene' is an autorelease object
     auto scene = Scene::create();

     // 'layer' is an autorelease object
     auto layer = HelloWorld::create();

     // add layer as a child to scene
     scene->addChild(layer);

     // return the scene
     return scene;
 }

 // on "init" you need to initialize your instance
 bool HelloWorld::init()
 {
     //////////////////////////////
     // 1. super init first
     if ( !Layer::init() )
     {
         return false;
     }

     Size visibleSize = Director::getInstance()->getVisibleSize();
     Point origin = Director::getInstance()->getVisibleOrigin();

     /////////////////////////////
     // 2. add a menu item with "X" image, which is clicked to quit the program
     //    you may modify it.

     // add a "close" icon to exit the progress. it's an autorelease object
     auto closeItem = MenuItemImage::create(
                                            "CloseNormal.png",
                                            "CloseSelected.png",
                                            CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));

     closeItem->setPosition(Point(origin.x + visibleSize.width - closeItem->getContentSize().width/ ,
                                 origin.y + closeItem->getContentSize().height/));

     // create menu, it's an autorelease object
     auto menu = Menu::create(closeItem, NULL);
     menu->setPosition(Point::ZERO);
     );

     /////////////////////////////
     // 3. add your codes below...

     // add a label shows "Hello World"
     // create and initialize a label

     auto label = LabelTTF::create();

     // position the label on the center of the screen
     label->setPosition(Point(origin.x + visibleSize.width/,
                             origin.y + visibleSize.height - label->getContentSize().height));

     // add the label as a child to this layer
     );

     // add "HelloWorld" splash screen"
     auto sprite = Sprite::create("HelloWorld.png");

     // position the sprite on the center of the screen
     sprite->setPosition(Point(visibleSize.width/ + origin.x, visibleSize.height/ + origin.y));

     // add the sprite as a child to this layer
     );

     ////// "开始" 精灵菜单
     Sprite* startSpriteNormal = Sprite::create("Demo1/start-up.png");
     Sprite* startSpriteSelected = Sprite::create("Demo1/start-down.png");
     MenuItemSprite* startMenuItem = MenuItemSprite::create(startSpriteNormal,
         startSpriteSelected,
         CC_CALLBACK_1(HelloWorld::menuItemStartCallback, this));
     startMenuItem->setPosition(Director::getInstance()->convertToGL(Point(, )));

     /// "设置" 图片菜单
     MenuItemImage* settingMenuItem = MenuItemImage::create(
         "Demo1/setting-up.png",
         "Demo1/setting-down.png",
         CC_CALLBACK_1(HelloWorld::menuItemSettingCallback, this));
     settingMenuItem->setPosition(Director::getInstance()->convertToGL(Point(, )));

     /// "帮助" 图片菜单
     MenuItemImage* helpMenuItem = MenuItemImage::create(
         "Demo1/help-up.png",
         "Demo1/help-down.png",
         CC_CALLBACK_1(HelloWorld::menuItemHelpCallback, this));
     helpMenuItem->setPosition(Director::getInstance()->convertToGL(Point(, )));

     Menu* mu = Menu::create(startMenuItem, settingMenuItem, helpMenuItem, NULL);
     mu->setPosition(Point::ZERO);
     this->addChild(mu);

     return true;
 }

 void HelloWorld::menuCloseCallback(Ref* pSender)
 {
 #if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
     MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
     return;
 #endif

     Director::getInstance()->end();

 #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
     exit();
 #endif
 }

 void HelloWorld::menuItemStartCallback(Ref* pSender)
 {
     MenuItem* item = (MenuItem*)pSender;
     log("Touch Start %p", item);

     auto sc = Setting::createScene();
 //    Director::getInstance()->replaceScene(sc);
     Director::getInstance()->pushScene(sc);
 }

 void HelloWorld::menuItemSettingCallback(Ref* pSender)
 {
     MenuItem* item = (MenuItem*)pSender;
     log("Touch Setting %p", item);

 }

 void HelloWorld::menuItemHelpCallback(Ref* pSender)
 {
     MenuItem* item = (MenuItem*)pSender;
     log("Touch Help %p", item);

 }
 #ifndef __SETTING_SCENE_H__
 #define __SETTING_SCENE_H__

 #include "cocos2d.h"

 class Setting : public cocos2d::Layer
 {
 public:
     static cocos2d::Scene* createScene();
     virtual bool init();

     void menuSoundToggleCallback(cocos2d::Ref* pSender);
     void menuMusicToggleCallback(cocos2d::Ref* pSender);
     void menuOkCallback(cocos2d::Ref* pSender);

     CREATE_FUNC(Setting);
 };

 #endif   // __SETTING_SCENE_H__
 #include "Setting.h"

 // using namespace cocos2d;
 USING_NS_CC;

 Scene* Setting::createScene()
 {
     // 'scene' is an autorelease object
     auto scene = Scene::create();
     // 'layer' is an autorelease object
     auto layer = Setting::create();

     scene->addChild(layer);
     return scene;
 }

 bool Setting::init()
 {
     if (!Layer::init())
     {
         return false;
     }
     Size visibleSize = Director::getInstance()->getVisibleSize();
     Point origin = Director::getInstance()->getVisibleOrigin();

     Sprite*bg = Sprite::create("Demo1/setting-back.png");
     bg->setPosition(Point(origin.x + visibleSize.width / , origin.y + visibleSize.height / ));
     this->addChild(bg);

     // 音效
     auto soundOnMenuItem = MenuItemImage::create(
         "Demo1/on.png",
         "Demo1/on.png");
     auto soundOffmenuItem = MenuItemImage::create(
         "Demo1/off.png",
         "Demo1/off.png");
     auto soundToggleMenuItem = MenuItemToggle::createWithCallback(
         CC_CALLBACK_1(Setting::menuSoundToggleCallback, this),
         soundOnMenuItem,
         soundOffmenuItem,
         NULL);
     soundToggleMenuItem->setPosition(Director::getInstance()->convertToGL(Point(, )));

     // 音乐
     auto musicOnMenuItem = MenuItemImage::create(
         "Demo1/on.png",
         "Demo1/on.png");
     auto musicOffMenuItem = MenuItemImage::create(
         "Demo1/off.png",
         "Demo1/off.png");
     auto musicToggleItem = MenuItemToggle::createWithCallback(
         CC_CALLBACK_1(Setting::menuMusicToggleCallback, this),
         musicOnMenuItem,
         musicOffMenuItem,
         NULL);
     musicToggleItem->setPosition(Director::getInstance()->convertToGL(Point(, )));

     // OK 按钮
     auto okMenuItem = MenuItemImage::create(
         "Demo1/ok-down.png",
         "Demo1/ok-up.png",
         CC_CALLBACK_1(Setting::menuOkCallback, this));
     okMenuItem->setPosition(Director::getInstance()->convertToGL(Point(, )));

     Menu* mn = Menu::create(soundToggleMenuItem,
         musicToggleItem,
         okMenuItem,
         NULL);
     mn->setPosition(Point::ZERO);
     this->addChild(mn);

     return true;
 }

 void Setting::menuSoundToggleCallback(cocos2d::Ref* pSender)
 {
     MenuItem* item = (MenuItem*)pSender;
     log("Touch Setting::Music %p", item);
 }

 void Setting::menuMusicToggleCallback(cocos2d::Ref* pSender)
 {
     MenuItem* item = (MenuItem*)pSender;
     log("Touch Setting::Music %p", item);
 }

 void Setting::menuOkCallback(cocos2d::Ref* pSender)
 {
     MenuItem* item = (MenuItem*)pSender;
     log("Touch Setting::Ok %p", item);
     Director::getInstance()->popScene();
 }

关键代码解释:

1)使用 replaceScene

auto  sc = Setting::createScene();

Director->getInstance()->replaceScene(sc);

用 Setting 场景,替换当前的场景。当前场景被是否。

2)使用 pushScene

auto  sc = Setting::createScene();

Director->getInstance()->pushScene(sc);

将当前场景挂起放入到场景堆栈中,然后切换到 Setting 场景

3)使用 popScene

Director->getInstance()->popScene();

将当前场景释放,从 场景堆栈的栈顶 调入 一个 场景到程序中。(如果场景堆栈中没有场景,那么程序退出)

 场景过度动画:

场景切换时是可以添加过渡动画的,场景过渡动画是由 TransitionScene 类和它的子类展示的。

过渡动画类的使用方法如下:

 auto sc = Setting::createScene();
 auto reScene = TransitionFade::create(0.4f, sc);
 Director::getInstance()->pushScene(reScene);

第2行代码,创建 过渡动画 TransitionScene 对象,它的create函数有2个参数,第1个是动画持续时间,第2个是场景对象。

第3行代码中, pushScene 函数使用的参数是过渡动画 TransitionScene 对象,而不是场景对象。

场景的声明周期:

一般情况下一个场景只需要一个层。场景的生命周期可以通过层的生命周期反映出来,通过重写层的生命周期函数,可以处理场景不同生命周期阶段的事件。

例如,可以在层进入函数(onEnter)中做一些初始化处理,而在层退出函数(onExit)中释放一些资源。

层的声明周期函数如下:

    // 初始化层 调用
    virtual bool init();
    // 进入层时调用
    virtual void onEnter();
    // 进入层而且过渡动画结束时调用
    virtual void onEnterTransitionDidFinish();
    // 退出层时调用
    virtual void onExit();
    // 退出层而且开始过渡动画时调用
    virtual void onExitTransitionDidStart();
    // 层对象被清除时调用
    virtual void cleanup();

层(layer)继承于节点(node),这些生命周期函数根本上是从Node继承而来。

在重写层的生命周期函数中,第一行代码应该是调用父类的函数。如果不调用父类函数,会导致层中动画、动作或计划无法执行。

代码示例:

 // 进入层时调用
 void HelloWorld::onEnter()
 {
     Layer::onEnter();
     log("HelloWorld::onEnter()----- start ");
     log("HelloWorld::onEnter()----- end ");
 }

 void HelloWorld::onEnterTransitionDidFinish()
 {
     Layer::onEnterTransitionDidFinish();
     log("HelloWorld::onEnterTransitionDidFinish()----- start ");
     log("HelloWorld::onEnterTransitionDidFinish()----- end ");
 }

 // 退出层时调用
 void HelloWorld::onExit()
 {
     Layer::onExit();
     log("HelloWorld::onExit()----- start ");
     log("HelloWorld::onExit()----- end ");
 }

 // 退出层而且开始过渡动画时调用
 void HelloWorld::onExitTransitionDidStart()
 {
     Layer::onExitTransitionDidStart();
     log("HelloWorld::onExitTransitionDidStart()----- start ");
     log("HelloWorld::onExitTransitionDidStart()----- end ");
 }

 // 层对象被清除时调用
 void HelloWorld::cleanup()
 {
     Layer::cleanup();
     log("HelloWorld::cleanup()----- start ");
     log("HelloWorld::cleanup()----- end ");
 }

如果 HelloWorld 是第1个场景,当启动 HelloWorld 场景时,它的调用顺序是:

HelloWorld::init()-------- start
HelloWorld::init()-------- end
HelloWorld::onEnter()----- start
HelloWorld::onEnter()----- end
HelloWorld::onEnterTransitionDidFinish()----- start
HelloWorld::onEnterTransitionDidFinish()----- end

多场景切换生命周期:  

1)使用 pushScene 函数 实现从 HelloWorld 场景进入 Setting 场景  

Setting::init()------------- start
Setting::init()------------- end
HelloWorld::onExitTransitionDidStart()----- start
HelloWorld::onExitTransitionDidStart()----- end
Setting::onEnter()----- start
Setting::onEnter()----- end
HelloWorld::onExit()----- start
HelloWorld::onExit()----- end
Setting::onEnterTransitionDidFinish()----- start
Setting::onEnterTransitionDidFinish()----- end 

2)使用 replaceScene 函数实现从 HelloWorld 场景进入 Setting 场景

Setting::init()------------- start
Setting::init()------------- end
HelloWorld::onExitTransitionDidStart()----- start
HelloWorld::onExitTransitionDidStart()----- end
Setting::onEnter()----- start
Setting::onEnter()----- end
HelloWorld::onExit()----- start
HelloWorld::onExit()----- end
Setting::onEnterTransitionDidFinish()----- start
Setting::onEnterTransitionDidFinish()----- end
HelloWorld::cleanup()----- start
HelloWorld::cleanup()----- end 

3)使用 popScene 函数实现从 Setting 层场景切回到 HelloWorld 场景

Setting::onExitTransitionDidStart()----- start
Setting::onExitTransitionDidStart()----- end
Setting::onExit()----- start
Setting::onExit()----- end
Setting::cleanup()----- start
Setting::cleanup()----- end
HelloWorld::onEnter()----- start
HelloWorld::onEnter()----- end
HelloWorld::onEnterTransitionDidFinish()----- start
HelloWorld::onEnterTransitionDidFinish()----- end 

cocos2d-x实战 C++卷 学习笔记--第6章 场景与层的更多相关文章

  1. cocos2d-x实战 C++卷 学习笔记--第4章 字符串 __String类

    前言: <cocos2d-x实战C++卷>学习笔记.(cocos2d-x 是3.0版本) 介绍 cocos2d-x 通用的字符串类  __String . 使用cocos2d::__Str ...

  2. cocos2d-x实战 C++卷 学习笔记--第7章 动作、特效(一)

    前言: 介绍cocos2d-x中的动作.特效. 动作: 动作(action)包括基本动作和基本动作的组合,这些基本动作有缩放.移动.旋转等,而且这些动作变化的速度也可以设定. 动作类是 Action. ...

  3. cocos2d-x实战 C++卷 学习笔记--第4章 使用菜单

    前言: 菜单中包含菜单项,菜单项类是 MenuItem ,每个菜单项都有三个基本状态:正常.选中和禁止. (MenuItem)菜单分类: (文本菜单)MenuItemLabel : MenuItemA ...

  4. cocos2d-x实战 C++卷 学习笔记--第4章 win32平台下中文乱码问题

    前言: 将GBK编码的字符串转为UTF-8编码.(通俗点说就是解决中文乱码问题) 简要介绍: 在Win32平台下通过 log 输出中文字符时,会出现中文乱码问题.同样的代码在 ios 和 Androi ...

  5. cocos2d-x实战 C++卷 学习笔记--第5章 精灵

    前言: 精灵类是Sprite类.它的子类有PhysicsSprite 和 Skin. PhysicsSprite 是物理引擎精灵类,而Skin是皮肤精灵类,用于骨骼动画. 创建Sprite精灵对象 创 ...

  6. cocos2d-x实战 C++卷 学习笔记--第4章 使用标签

    前言: 介绍cocos2d-x中 标签类. cocos2d-x中 标签类 主要有三种:LabelTTF, LabelAtlas, 和 LabelBMFont.此外,在Cocos2d-x 3.x之后推出 ...

  7. UNP学习笔记(第二章:传输层)

    本章的焦点是传输层,包括TCP.UDP和SCTP. 绝大多数客户/服务器网络应用使用TCP或UDP.SCTP是一个较新的协议. UDP是一个简单的.不可靠的数据报协议.而TCP是一个复杂.可靠的字节流 ...

  8. Docker技术入门与实战 第二版-学习笔记-10-Docker Machine 项目-2-driver

    1>使用的driver 1〉generic 使用带有SSH的现有VM/主机创建机器. 如果你使用的是机器不直接支持的provider,或者希望导入现有主机以允许Docker Machine进行管 ...

  9. Docker技术入门与实战 第二版-学习笔记-8-网络功能network-3-容器访问控制和自定义网桥

    1)容器访问控制 容器的访问控制,主要通过 Linux 上的 iptables防火墙来进行管理和实现. iptables是 Linux 上默认的防火墙软件,在大部分发行版中都自带. 容器访问外部网络 ...

随机推荐

  1. 松下蓄电池与UPS使用和维护

      使用条件及环境1.充电电流(浮充使用):0.15CA以下2.放电电流范围:0.05CA-3CA3.环境温度:0℃-40℃ (适宜的温度是25℃) 4.充电电压:(12V电池推荐值)   周围温度 ...

  2. [Objective-c 基础 - 2.7] 构造方法、重写init方法

    A.id 万能指针,可以指向任何对象,实质是NSObject的指针,使用的时候不用加上*   B.NSObject中得类方法new 1.完整地创建一个可用对象步骤 (1)分配存储空间 + alloc ...

  3. hql查询技巧

    要擅于利用对象之间映射的集合去查与其关联的对象,而不是直接在dao层重新写查询的方法,其实,hibernate正是对复杂查询的一种解放,既然有现成的东西,何必再去闭门造车,而且造出来的还是个旧车. 查 ...

  4. 把pgboucer做成postgresql服务

    把pgbouncer启动命令加入到postgresql服务配置里面.这样方便操作 vi /etc/init.d/postgresql 加入如下红色命令.路径换成你的pgbouncer安装目录 in s ...

  5. 【转】C++及java在内存分配上的区别

    转自:http://blog.csdn.net/qinghezhen/article/details/9116053 C++内存分配由五个部分组成:栈.堆.全局代码区.常量区.程序代码区.如下图所示: ...

  6. CPU相关信息

    unit untCpuInfo;interface{ 获取 CPU 制造商 }function GetCpuFactory: String;{ 获取 CPU 家族系统 }function GetCpu ...

  7. iOS开发——基本常识篇&各种控件默认高度

    各种控件默认高度   1.状态栏 状态栏一般高度为20像素,在打手机或者显示消息时会放大到40像素高,注意,两倍高度的状态栏在好像只能在纵向的模式下使用.如下图 用户可以隐藏状态栏,也可以将状态栏设置 ...

  8. 文件和目录之utime函数

    一个文件的访问和修改时间可以用utime函数更改. #include <utime.h> int utime( const char *pathname, const struct uti ...

  9. 多线程NSOperation

      NSOperation(经常使用): 1.为什么会有NSOperation?弥补gcd的一些问题:1)下载为例子:如果gcd放到队列中的block操作面对网络有问题,block之外无法取消bloc ...

  10. UIPickerView

    1.UIPickView什么时候用? 通常在注册模块,当用户需要选择一些东西的时候,比如说城市,往往弹出一个PickerView给他们选择. UIPickView常见用法,演示实例程序 1> 独 ...