经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » 游戏设计 » 查看文章
?Cocos2d-x 学习笔记(3.1) Scene 场景与场景切换
来源:cnblogs  作者:深潮  时间:2019/8/16 9:19:41  对本文有异议

1. Scene 简介

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

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

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

场景Scene直接继承了Node。

2. Scene 类

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

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

createWithSize方法同理。

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

3. Director 与 Scene

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

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

  1. Scene *_runningScene;
  2. Scene *_nextScene;

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

  1. Vector<Scene*> _scenesStack;

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

  1.   bool _sendCleanupToScene;
  2.   bool isSendCleanupToScene() { return _sendCleanupToScene; }

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

导演里的场景相关方法:

  1. void runWithScene(Scene *scene);
  2. void pushScene(Scene *scene);
  3. void popScene();
  4. void popToRootScene();
  5. void popToSceneStackLevel(int level);
  6. void replaceScene(Scene *scene);
  7. void end();
  8. void pause();
  9. void resume();
  10. void restart();
  11. void stopAnimation();
  12. void startAnimation();
  13. void drawScene();

4. 在 Director 使用 Scene

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

runWithScene(scene)

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

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

- pushScene(scene)

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

  1. _scenesStack.pushBack(scene);
  2. _nextScene = scene;

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

- drawScene()

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

  1. if (_nextScene)
  2. {
  3. setNextScene(); // nextScene赋给runningScene,之后nextScene为空
  4. }

- 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。

  1. void Director::pushScene(Scene *scene)
  2. {
  3. _sendCleanupToScene = false;
  4. _scenesStack.pushBack(scene);
  5. _nextScene = scene;
  6. }

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

- popScene()

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

  1. void Director::popScene(void)
  2. {
  3. CCASSERT(_runningScene != nullptr, "running scene should not null");
  4. _scenesStack.popBack();
  5. ssize_t c = _scenesStack.size();
  6. if (c == 0)
  7. {
  8. end();
  9. }
  10. else
  11. {
  12. _sendCleanupToScene = true;
  13. _nextScene = _scenesStack.at(c - 1);
  14. }
  15. }

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

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

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

原文链接:http://www.cnblogs.com/deepcho/p/cocos2dx-scene.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号