cocos2d-x实战 C++卷 学习笔记--第6章 场景与层
前言:
一个场景(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章 场景与层的更多相关文章
- cocos2d-x实战 C++卷 学习笔记--第4章 字符串 __String类
前言: <cocos2d-x实战C++卷>学习笔记.(cocos2d-x 是3.0版本) 介绍 cocos2d-x 通用的字符串类 __String . 使用cocos2d::__Str ...
- cocos2d-x实战 C++卷 学习笔记--第7章 动作、特效(一)
前言: 介绍cocos2d-x中的动作.特效. 动作: 动作(action)包括基本动作和基本动作的组合,这些基本动作有缩放.移动.旋转等,而且这些动作变化的速度也可以设定. 动作类是 Action. ...
- cocos2d-x实战 C++卷 学习笔记--第4章 使用菜单
前言: 菜单中包含菜单项,菜单项类是 MenuItem ,每个菜单项都有三个基本状态:正常.选中和禁止. (MenuItem)菜单分类: (文本菜单)MenuItemLabel : MenuItemA ...
- cocos2d-x实战 C++卷 学习笔记--第4章 win32平台下中文乱码问题
前言: 将GBK编码的字符串转为UTF-8编码.(通俗点说就是解决中文乱码问题) 简要介绍: 在Win32平台下通过 log 输出中文字符时,会出现中文乱码问题.同样的代码在 ios 和 Androi ...
- cocos2d-x实战 C++卷 学习笔记--第5章 精灵
前言: 精灵类是Sprite类.它的子类有PhysicsSprite 和 Skin. PhysicsSprite 是物理引擎精灵类,而Skin是皮肤精灵类,用于骨骼动画. 创建Sprite精灵对象 创 ...
- cocos2d-x实战 C++卷 学习笔记--第4章 使用标签
前言: 介绍cocos2d-x中 标签类. cocos2d-x中 标签类 主要有三种:LabelTTF, LabelAtlas, 和 LabelBMFont.此外,在Cocos2d-x 3.x之后推出 ...
- UNP学习笔记(第二章:传输层)
本章的焦点是传输层,包括TCP.UDP和SCTP. 绝大多数客户/服务器网络应用使用TCP或UDP.SCTP是一个较新的协议. UDP是一个简单的.不可靠的数据报协议.而TCP是一个复杂.可靠的字节流 ...
- Docker技术入门与实战 第二版-学习笔记-10-Docker Machine 项目-2-driver
1>使用的driver 1〉generic 使用带有SSH的现有VM/主机创建机器. 如果你使用的是机器不直接支持的provider,或者希望导入现有主机以允许Docker Machine进行管 ...
- Docker技术入门与实战 第二版-学习笔记-8-网络功能network-3-容器访问控制和自定义网桥
1)容器访问控制 容器的访问控制,主要通过 Linux 上的 iptables防火墙来进行管理和实现. iptables是 Linux 上默认的防火墙软件,在大部分发行版中都自带. 容器访问外部网络 ...
随机推荐
- 松下蓄电池与UPS使用和维护
使用条件及环境1.充电电流(浮充使用):0.15CA以下2.放电电流范围:0.05CA-3CA3.环境温度:0℃-40℃ (适宜的温度是25℃) 4.充电电压:(12V电池推荐值) 周围温度 ...
- [Objective-c 基础 - 2.7] 构造方法、重写init方法
A.id 万能指针,可以指向任何对象,实质是NSObject的指针,使用的时候不用加上* B.NSObject中得类方法new 1.完整地创建一个可用对象步骤 (1)分配存储空间 + alloc ...
- hql查询技巧
要擅于利用对象之间映射的集合去查与其关联的对象,而不是直接在dao层重新写查询的方法,其实,hibernate正是对复杂查询的一种解放,既然有现成的东西,何必再去闭门造车,而且造出来的还是个旧车. 查 ...
- 把pgboucer做成postgresql服务
把pgbouncer启动命令加入到postgresql服务配置里面.这样方便操作 vi /etc/init.d/postgresql 加入如下红色命令.路径换成你的pgbouncer安装目录 in s ...
- 【转】C++及java在内存分配上的区别
转自:http://blog.csdn.net/qinghezhen/article/details/9116053 C++内存分配由五个部分组成:栈.堆.全局代码区.常量区.程序代码区.如下图所示: ...
- CPU相关信息
unit untCpuInfo;interface{ 获取 CPU 制造商 }function GetCpuFactory: String;{ 获取 CPU 家族系统 }function GetCpu ...
- iOS开发——基本常识篇&各种控件默认高度
各种控件默认高度 1.状态栏 状态栏一般高度为20像素,在打手机或者显示消息时会放大到40像素高,注意,两倍高度的状态栏在好像只能在纵向的模式下使用.如下图 用户可以隐藏状态栏,也可以将状态栏设置 ...
- 文件和目录之utime函数
一个文件的访问和修改时间可以用utime函数更改. #include <utime.h> int utime( const char *pathname, const struct uti ...
- 多线程NSOperation
NSOperation(经常使用): 1.为什么会有NSOperation?弥补gcd的一些问题:1)下载为例子:如果gcd放到队列中的block操作面对网络有问题,block之外无法取消bloc ...
- UIPickerView
1.UIPickView什么时候用? 通常在注册模块,当用户需要选择一些东西的时候,比如说城市,往往弹出一个PickerView给他们选择. UIPickView常见用法,演示实例程序 1> 独 ...