1. Scene 简介

游戏中我们看到/看不到的所有元素都是展示在场景之Scene上。

我们可以把场景比作放在地上的没盖纸箱,层Layer是纸箱里堆放的玻璃,Sprite等元素画在玻璃Layer上,这样我们从纸箱上往下看就能看到这一个场景。场景切换时,是更换不同的纸箱。

概括的说,导演管理N个场景,场景管理N个层,层管理N个精灵等等小的元素,每个精灵有N个动作Timer等等。

场景Scene直接继承了Node。

场景创建时,调用init方法初始化。

在主循环中先后执行场景的:onEnter ==> onEnterTransitionDidFinish ==> onExitTransitionDidStart ==> onExit

场景进入窗口前,设为导演的nextScene,导演通过setNextScene调用onEnter onEnterTransitionDidFinish。场景退出窗口前,因为导演的nextScene被设为其他场景,正在运行的本场景执行onExitTransitionDidStart onExit。

2. Scene 类

构造函数中锚点默认(0.5,0.5)。主要方法是create方法。

create方法new一个场景,并调用init方法,init中获取屏幕大小,调用initWithSize,执行setContentSize设置了场景的大小。

createWithSize方法同理。

我们可以自定义一个继承了Scene的场景,在自定义场景中,重写init方法和onEnter onExit等方法,实现我们自己的场景。

3. Director 与 Scene

导演能够管理场景,实现场景的执行和切换。

导演有两个场景指针变量。

    Scene *_runningScene;
Scene *_nextScene;

runningScene是正在前台的场景。nextScene如果存在的话,将是在下一帧成为runningScene的场景。

    Vector<Scene*> _scenesStack;

导演类的场景指针存储在Vector容器scenesStack中,从名字可以知道是按栈的方式存储。

  bool _sendCleanupToScene;
  bool isSendCleanupToScene() { return _sendCleanupToScene; }

bool变量sendCleanupToScene决定了被替换的场景是否收到cleanup信息。当新的场景是被replace的,旧场景收到cleanup信息;新场景被push的,旧场景不会被清理。

导演里的场景相关方法:

    void runWithScene(Scene *scene);
void pushScene(Scene *scene);
void popScene();
void popToRootScene();
void popToSceneStackLevel(int level);
void replaceScene(Scene *scene);
void end();
void pause();
void resume();
void restart();
void stopAnimation();
void startAnimation();
void drawScene();

4. 在 Director 使用 Scene

在Application run方法中,首先游戏初始化执行的是AppDelegate applicationDidFinishLaunching方法。该方法调用了我们自己写的场景的init方法,在得到场景指针scene后,执行director->runWithScene(scene)。

runWithScene(scene)

void Director::runWithScene(Scene *scene)
{
CCASSERT(scene != nullptr, "This command can only be used to start the Director. There is already a scene present.");
CCASSERT(_runningScene == nullptr, "_runningScene should be null"); pushScene(scene);
startAnimation();
}

该方法要求导演的runningScene为空。继续看。

- pushScene(scene)

该方法先把标志sendCleanupToScene置false。然后执行:

    _scenesStack.pushBack(scene);
_nextScene = scene;

场景加到了场景栈里,并将nextScene设为我们自定义的场景。

- drawScene()

mainLoop的drawScene方法中,调度器update之后执行:

    if (_nextScene)
{
setNextScene(); // nextScene赋给runningScene,之后nextScene为空
}

- setNextScene()

简要的说,该方法把nextScene赋给了runningScene,此时的runningScene如果不是过渡场景,将执行enter的两个方法。

导演在当前帧时nextScene存在的情况下才能执行该方法,进入下一个场景。

5. 场景切换

Director场景切换方法分为两种:

  1. replaceScene:新场景替代了原场景,原场景将被cleanup。新场景压入了栈。

  2. pushScene popScene:push的新场景替代了原场景,原场景只是“隐藏”了,pop方法会“还原”原场景。新场景没有压入栈。

- replaceScene(Scene *scene)

实现了参数scene替代当前的scene。参数scene被压入栈顶,且成为nextScene。

1. 如果runningScene为空,执行runWithScene(scene),方法结束。

2. 如果参数scene等于nextScene,方法结束,不用替换场景。

3. 如果存在nextScene,先判断nextScene是否处于running状态(onEnter之后,onExit之前),如是,对其执行onExit。对nextScene执行cleanup()并赋nullptr,清理了nextScene。

4. _sendCleanupToScene = true,因为replaceScene场景切换需要cleanup原先的runningScene。

_sendCleanupToScene唯一的用处是在每一帧setNextScene()之中。在将nextScene赋给runningScene之前,需要判断该值,为true时,对runningScene执行cleanup。

5. scenesStack栈顶的scene替换为参数scene,并且nextScene指向参数scene。

- pushScene(Scene *scene)

代码精简后很简单。push方法将参数scene压入栈顶且成为nextScene。

void Director::pushScene(Scene *scene)
{
_sendCleanupToScene = false;
_scenesStack.pushBack(scene);
_nextScene = scene;
}

_sendCleanupToScene置false,因为此种场景变换不要对原场景cleanup。

- popScene()

简要的说,pop方法将栈顶scene作为nextScene,_sendCleanupToScene置true,导致当前runningScene将被cleanup。

void Director::popScene(void)
{
CCASSERT(_runningScene != nullptr, "running scene should not null");
_scenesStack.popBack();
ssize_t c = _scenesStack.size();
if (c == )
{
end();
}
else
{
_sendCleanupToScene = true;
_nextScene = _scenesStack.at(c - );
}
}

在从栈中popBack之后,若场景栈为空,此时将无法恢复原场景,说明pop没有和push搭配使用,导致导演在下一帧结束程序。

6. 过渡场景在场景切换中的使用

请看本文:Cocos2d-x 学习笔记(3.2) TransitionScene 过渡场景

‎Cocos2d-x 学习笔记(3.1) Scene 场景与场景切换的更多相关文章

  1. Android(java)学习笔记233: 远程服务的应用场景(移动支付案例)

    一. 移动支付:       用户需要在移动终端提交账号.密码以及金额等数据 到 远端服务器.然后远端服务器匹配这些信息,进行逻辑判断,进而完成交易,返回交易成功或失败的信息给移动终端.用户提交账号. ...

  2. Android(java)学习笔记176: 远程服务的应用场景(移动支付案例)

    一. 移动支付:       用户需要在移动终端提交账号.密码以及金额等数据 到 远端服务器.然后远端服务器匹配这些信息,进行逻辑判断,进而完成交易,返回交易成功或失败的信息给移动终端.用户提交账号. ...

  3. Android学习笔记之滑动翻页(屏幕切换)

    如何实现手机上手动滑动翻页效果呢?呵呵,在这里我们就给你们介绍一下吧. 一般实现这个特效会用到一个控件:ViewFlipper <1>View切换的控件—ViewFlipper 这个控件是 ...

  4. Cocos2d-x 3.2 学习笔记(十五)保卫萝卜 场景与数据

         保卫萝卜~场景的思路以及数据的存储.      学习要写笔记,记录自己的步骤. 一.场景构建Tiled      关于Tiled网上有一大堆的教程,这个比较好用,特别是构建塔防类的游戏极其简 ...

  5. 二、Laya学习笔记 ---- Laya中如何新建一个场景UI并使用

    因为我之前是用Egret的,Egret是场景皮肤HomeSceneSkin.exml,然后在场景代码HomeScene代码中为该场景赋值皮肤this.skinName = "HomeScen ...

  6. Redis学习笔记--五种数据类型的使用场景

    String 1.String 常用命令: 除了get.set.incr.decr mget等操作外,Redis还提供了下面一些操作: 获取字符串长度 往字符串append内容 设置和获取字符串的某一 ...

  7. [javase学习笔记]-8.5 statickeyword的使用场景

    这一节我们来看一下在我们开发的过程中,在什么时候我们要用到statickeyword进行静态修饰. 我们这里所说的静态.无非就是两种.一种是静态变量,一种是静态函数,我们分这两种情况进行说明stati ...

  8. Jmeter 学习笔记 1 - Logic Controller -组织执行场景

    using this website to practice performance testing: http://advantageonlineshopping.com/#/ Jemeter ho ...

  9. git 学习笔记 —— 保留/丢弃当前分支修改并切换至其他分支

    笔者在本地终端进行 git 工作目录的相关处理时,遇到由于某种情况需要使用 git checkout 命令切换到其他分支的情景.此时,若已经对当前分支做了一定的修改,则直接切换分支时 git 会提示错 ...

随机推荐

  1. LeetCode 把二叉搜索树转换为累加树

    第538题 给定一个二叉搜索树(Binary Search Tree),把它转换成为累加树(Greater Tree),使得每个节点的值是原来的节点值加上所有大于它的节点值之和. 例如: 输入: 二叉 ...

  2. cent OS 7 忘记 root 密码

    1. 在如下图, 选择系统的界面 按 e 2. 移动光标到文件底部, 修改如下两个地方(初始化 shell文件 并设置可读写), Ctrl x 退出并启动 shell 3. 如下界面 输入命令 mou ...

  3. java-整型数值 用 16进制转换、2进制转换-Integer.toHexString

    负数为什么要用补码表示 可以将符号位和其它位统一处理 减法也可按加法来处理 另外,两个用补码表示的数相加时,如果最高位(符号位)有进位,则进位被舍弃 正数:原码.反码.补码相同. 负数:反码符号位不变 ...

  4. cp -rf 操作时依然会提示覆盖

    在linux上经常会使用cp -rf命令,该命令就是强制覆盖指定目录下的文件,但有时使用该命令依然会提示是否覆盖,cp命令的参数有如下一些: 参数说明: -a:此选项通常在复制目录时使用,它保留链接. ...

  5. js校验对象是否全部为空

    function judgeIsNotBlank(obj) { var bool = true; var arr = Object.keys(obj); ; for(var key in obj){ ...

  6. .net core 3.0 Signalr - 实现一个业务推送系统

    ## 介绍 ASP.NET Core SignalR 是一个开源代码库,它简化了向应用添加实时 Web 功能的过程. 实时 Web 功能使服务器端代码能够即时将内容推送到客户端. SignalR 的适 ...

  7. asp.net编译中出现 数据库 'C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA\test1.mdf' 已存在。请选择其他数据库名称。

    关于asp.net编译中出现数据库 'C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA\test1.mdf ...

  8. .Net Core 商城微服务项目系列(十三):搭建Log4net+ELK+Kafka日志框架

    之前是使用NLog直接将日志发送到了ELK,本篇将会使用Docker搭建ELK和kafka,同时替换NLog为Log4net. 一.搭建kafka 1.拉取镜像 //下载zookeeper docke ...

  9. python 关于excel弹窗——请注意,您的文档的部分内容可能包含了文档检查器无法删除的个人信息解决方法

    参考https://www.cnblogs.com/Jacklovely/p/6582732.html 这个问题的原因是由于工作簿包含宏.ActiveX控件等内容, 而Excel被设置为在保存文件时自 ...

  10. 快学Scala 第十课 (包和包对象)

    Scala包定义: 嵌套式: package a1 { class a1Class{ val age = 10 } package a2 { class PackageTest { def main( ...