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 上默认的防火墙软件,在大部分发行版中都自带. 容器访问外部网络 ...
随机推荐
- 大数记录之,大数乘整型数nyoj832
想到了一个题目:对决二http://acm.nyist.net/JudgeOnline/problem.php?pid=832 但是发现有一道题目是相似的:http://acm.nyist.net/J ...
- 用Modelsim仿真QuartusII综合后网表时库的添加方法(转)
这两天做综合后仿真,发现FPGA器件库又不会加了,无奈上网找方法.说起来不好意思,很早就接触Modelsim这个仿真软件了,可是没有好好琢磨.把这两天找的方法贴出来,再加上自己的理解,以后忘了可以上博 ...
- 【Stage3D学习笔记续】山寨Starling(八):核心优化(批处理)的实现
批处理是使GPU进行高效绘制的一种技术手段,也是整个渲染流程中最核心的技术,到目前为止我们并没有使用到这种技术手段,下面我们看看我们现在的渲染机制. 先想一想我们最开始是怎么向GPU绘制一幅图像的,可 ...
- java.io.File中的pathSeparator与separator的区别
先总的说一下区别:File.pathSeparator指的是分隔连续多个路径字符串的分隔符,例如:java -cp test.jar;abc.jar HelloWorld就是指“;” Fi ...
- 【35】考虑virtual方法以外的其他选择
1.使用Non-Virtual Interface 实现方法模版 将虚方法声明为private,子类重写private的虚方法,在父类中通过public方法调用虚方法.NVI的优点是:可以在虚方法之前 ...
- Codeforces Round #325 (Div. 2) F. Lizard Era: Beginning meet in the mid
F. Lizard Era: Beginning Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/5 ...
- 计算机思维or人的思维
计算机领域就会有计算机领域的一些特性和一些思维方式,或者说有他自己的一些问题,须要用相应的思维方式来进行理解它,从而更好的驾驭他.有些时候遇到的一些问题,自己想却想不明确,也是由于我们没有把自己当做一 ...
- win7系统升家庭版级为旗舰版的方法
在使用的便利性上,两者没有太大差别,不过有些高级功能是家庭版所没有的,所以我们很多人都希望升级为旗舰版,那么我们需要重新安装系统吗?显然没有这么麻烦,我们只需要简单的几个步骤即可. 步骤/方法 ...
- php输出错误信息
error_reporting(E_ALL); ini_set('display_errors','on'); header("Content-Type:text/html;charset ...
- 多系统通讯-DotNetMQ
很久都没有写博客了,从15年4月份一直忙到现在,我才有时间去做梳理和总结,因为我提离职了,感觉整个世界突然变得不一样,随着而来的就是心情的放松,写一篇文章也是对过去一年多工作的梳理,加深印象 积累和沉 ...