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 上默认的防火墙软件,在大部分发行版中都自带. 容器访问外部网络 ...
随机推荐
- Go: using a pointer to array
下面的不是指针指向数组,而是指针指向Slice I'm having a little play with google's Go language, and I've run into someth ...
- [六]SpringMvc学习-文件上传
1.单文件上传 1.1修改配置文件 <bean id="multipartResolver" class="org.springframework.web.mult ...
- .NET MVC4 ApiController拦截器的使用
目前在公司新开发了一个项目,第一次正式使用.NET MVC4来搭建,用拦截器来处理权限验证. 自定义拦截器需继承ActionFilterAttribute类,重写OnActionExecuting和O ...
- careercup-C和C++ 13.2
13.2 浅析哈希表和STL map.对比哈希表和STL map.哈希表是怎么实现的?如果输入数据规模不大, 我们可以使用什么数据结构来代替哈希表. 解答 对比哈希表和STL map 在哈希表中,实值 ...
- 学习笔记之Shell脚本的输出重定向
shell http://baike.baidu.com/link?url=qN3THt5ZJhQtwRJJkakWdz5-vZp4V9H3OmNP97XNhaoL-dqU-6rrFrYfHXmYv6 ...
- [Effective C++ --017]以独立语句将newed对象置入智能指针
这一节也比较简单,先假设我们有如下的函数: int foo(); void memFoo(shared_ptr<T> pw, int foo); 现在假设我们要调用memFoo函数: me ...
- 路径(keyPath)、键值编码(KVC)和键值观察(KVO)
键路径 在一个给定的实体中,同一个属性的所有值具有相同的数据类型. 键-值编码技术用于进行这样的查找—它是一种间接访问对象属性的机制. - 键路径是一个由用点作分隔符的键组成的字符串,用于指定一个连接 ...
- DEM渲染洼地淹没图(转)
http://blog.csdn.net/kikitamoon/article/details/18700555 首先要准备基础数据,一张DEM栅格图. 然后将掩膜水位以下的数据提取出来以备后用.这里 ...
- symonfy 项目根目录下没有 bin/console 文件的解决方法
“Could not open input file: bin/console” Error comes when try to Run the Symfony Application 在采纳的答案中 ...
- android之手动安装apk到模拟器
一.将apk放到SDK的指定路径 二.打开命令行 三.安装apk到模拟器 此处遇到无法找到主机,解决办法: 发现是进程2512堵塞导致的 进入powershell 查看进程 发现2512进程是360手 ...