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 上默认的防火墙软件,在大部分发行版中都自带. 容器访问外部网络 ...
随机推荐
- APUE读书笔记-第17章-高级进程间通信
17.1 引言 *两种高级IPC:基于STREAMS的管道(STREAMS-based pipe)以及UNIX域套接字(UNIX domain socket)可以在进程间传送打开文件描述符.服务进程可 ...
- C#.NET数据库访问类DBHelper
这是一个与C# .NET通用的数据库访问类,包含了工厂模式.事务处理等安全机制. 调用方式: DBHelper db = new DBHelper(); DbCommand cmd = db.GetS ...
- C#抽象工厂模式的几种实现方法及比较
C#抽象工厂模式的几种实现方法及比较 本文转自:http://hi.baidu.com/tufeivista/blog/item/2ca9702978dcc6fb99250a81.html 利用设计模 ...
- Go2Shell
1.背景 windows系统可以轻而易举地拿到文件所在目录, 但是mac显得想拿文件目录有点蛋疼.而Go2Shell可以快速定位到文件所在的目录. 2.安装配置 选择默认打开的终端软件 3.使用 进入 ...
- 序列化与反序列化Serialize&Deserialize
序列化是指一个对象的实例可以被保存,保存成一个二进制串,当然,一旦被保存成二进制串,那么也可以保存成文本串了.比如,一个计数器,数值为2,我们可以用字符串“2”表示.如果有个对象,叫做connter, ...
- iOS 获取当前月份的天数(转)、
转:http://www.cnblogs.com/kingbo/p/3966855.html . 获取当前月份有多少天 NSCalendar *calendar = [NSCalendarcurren ...
- hdu 4104
先排序,再动态规划.须要优化 #include<iostream> #include<cstdio> #include<cstring> #include<s ...
- SQL书写技巧
SQL书写技巧: 1.针对分区表,如果可以使用分区条件的,一定要加分区条件.分区条件的使用,可以减少不必要的数据访问,加快查询数据,如TB_CSV_ACCEPT_FLOW_OPERATOR表,以acc ...
- 标准I/O库之缓冲
标准I/O库提供缓冲的目的是尽可能减少使用read和write调用的次数.它也对每个I/O流自动地进行缓冲管理,从而避免了应用程序需要考虑这一点所带来的麻烦. 标准I/O提供了三种类型的缓冲: (1) ...
- php读取图片成二进制流输出
header( "Content-type: image/jpeg");$PSize = filesize('1.jpg');$picturedata = fread(fopen( ...