我们之前讲了场景图(Scene Graph) 的概念,继续之前你先要知道

  • 场景图决定了场景内节点对象的渲染顺序
  • 渲染时 z-order 值大的节点对象会后绘制,值小的节点对象先绘制

HelloWorld

你还记得HelloWorld场景是如何启动的么?回看我们工程里的AppDelegate.cpp,滚到applicationDidFinishLaunching()的尾部:

// create a scene. it's an autorelease object
auto helloWorldscene = HelloWorld::createScene();
// run
director->runWithScene(helloWorldscene);

Ctrl+鼠标左键 点选createScene()查看定义,可以看到这个函数在HelloWorldScnen.h内声明,在HelloWorldScnen.cpp内定义

// HelloWorldScnen.h
static cocos2d::Scene* createScene(); // HelloWorldScnen.cpp
Scene* HelloWorld::createScene()
{
return HelloWorld::create();
}

我们可以通过该函数获取一个HelloWorld场景对象

之后就是场景的初始化,菜单,精灵等对象的Set都在这里进行

bool HelloWorld::init()
{
...
}

最后我们看到一个回调函数

void HelloWorld::menuCloseCallback(Ref* pSender)
{
//Close the cocos2d-x game scene and quit the application
Director::getInstance()->end();
}

C++基础差的同学可能还不理解回调的概念,但你只需要知道,这个函数实现了:HelloWorld场景内点击关闭按可钮关闭窗口 的功能,就行了、

SecondScene

现在我们对着HelloWorld的代码来创建一个SecondScene

和HelloWorld一样,首先我们需要一份SecondScene.h存放声明,然后是一份SecondScene.cpp存放定义

注意VS内新建文件时,一定要保存到Class文件夹内,不然你是不能直接include“xxxxxx”的(万恶的VS默认保存路径不是Class

修改到项目目录下的Class

SecondScene.h

首先是套一层宏保护到头尾

#ifndef __SECOND_SCENE_H__
#define __SECOND_SCENE_H__ #endif // __SECOND_SCENE_H__

然后

#include "cocos2d.h"

现在我开始我们要做一点点小变化,我们让SecondScene继承Layer而不是Scene

class SecondScene : public cocos2d::Layer {
public:
static cocos2d::Scene* createScene();
virtual bool init();
CREATE_FUNC(SecondScene);
//暂时不需要回调函数
};

实际上之前的cocos实例工程里HelloWorld都是继承自Layer的,不知为何现在改了,但是无妨,我们借此机会介绍Layer和Scene的区别

SecondScene.cpp

首先要include我们之前写好的SecondScene.h,为了方便我们也和HelloWorld一样using namespace cocos2d

你可能看到了HelloWorld.cpp里写的是USING_NS_CC而不是using namespace cocos2d,但其实效果是一样的

接下来我们定义creatSceen()函数,也和HelloWorld::createScene()略有不同

Scene* SecondScene::createScene() {
//创建一个Scene类的对象scene
auto scene = Scene::create();
//创建一个SecondScene类的对象layer
auto SecondScene = SecondScene::create();
//把layer添加到scene里
scene->addChild(layer);
//返回scene
return scene;
}

理解起来很简单:首先我们创建了一个Scene类的对象scene,然后创建了一个SecondScene类的对象layer(别忘了我们的SecondScene继承自layer),再把layer添加到了scene里,最后返回我们的scene

之后就可以开始写初始化函数了

bool SecondScene::init() {
auto visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin(); Label* label = Label::create("Second Test", "fonts/Marker Felt.ttf", 24);
label->setPosition(
Vec2(
origin.x + visibleSize.width / 2,
origin.y + visibleSize.height - label->getContentSize().height
)
); this->addChild(label); // 默认z-order=0 return true;
}

我们不用加太多东西,加入一个label让自己知道这是SecondScene场景就行

现在我们去程序的入口,AppDelegate.cpp里看看,还记得启动HelloWorld场景的那两行代码么,我们改成启动SecondScene场景:

(记得先要加入#include "SecondScene.h"到AppDelegate.cpp里)

// create a scene. it's an autorelease object
auto helloWorldscene = HelloWorld::createScene();
// run
director->runWithScene(helloWorldscene);

改成

auto secondScene = SecondScene::createScene();
director->runWithScene(secondScene);

运行测试:

没有问题

场景切换

接下来我们把AppDelegate.cpp还原回去(Crtl+Z),让程序运行时还是从HelloWorld场景开始,然后尝试使用回调函数切换到SecondScene

由于我们要在HelloWorld切换到Second,所以我们需要在HelloWorld场景里添加一个回调事件,刚好HelloWolrd里就有一个关闭按钮的回调,我们改改代码就行(这里重点是演示如何切换,真的不是我懒)

追踪到HelloWorld::menuCloseCallback()

Director::getInstance()->END改成

Director::getInstance()->replaceScene(
SecondScene::createScene()
);

运行测试,不出意外再点击HelloWorld右下角的关闭按钮,就会一瞬间切换到Second

切换动画

Cocos内置了很多切换场景的动画,比如

Director::getInstance()->replaceScene(
TransitionSlideInT::create(
3.0f, SecondScene::createScene()
)
);

运行,Second会在3秒内从上平滑切换掉HelloWorld

别的切换动画就不赘述了,和Actions又异曲同工之妙,各自己试试吧

场景栈

我们之前都是在使用replaceScene进行场景切换,replaceScene会使前一个场景被释放(简单来说就是删掉了,不再占用内存,想找回来只能重新创建一个),节省了内存资源,但有时我们不希望场景被释放怎么办呢

Cocos还提供了 推进pushScene()和弹出popScene两种方法,把一系列场景存储到栈内,按需弹出(释放)和推进新场景

是一种数据结构,你可以简单理解为一个弹匣,对栈有两种操作:

  1. 入栈(push),装入子弹
  2. 出栈(pop),射出子弹

子弹总是最上面的先被射出(pop时栈顶的元素最先出栈),也就是“先进后出”

新加入场景时使用pushScene(),新旧场景就会被存入场景栈,新在上旧在下(也就是说旧的场景没有释放),popScene会将新的场景释放,旧的场景就被弹了上来原来的位子,显示旧场景

你可以在场景初始化函数内写一段等待x秒的代码(换个思路,可以写一个计时器),验证pop后显示的旧场景不是新创建的:

bool HelloWorld::init()
{
... for(int i = 0; i <19999999; i++)// 耗时操作 ...
}

发挥你的奇思妙想,还有什么方法,自己实验一下

层和场景

这个好理解,想想你玩过的2d游戏,或者Photoshop的图层界面,一个场景里可以有好几个层

场景内创建层很简单:

Layer* layer2 = Layer::create();

当然一个层必须添加到场景内才会生效,层无法离开场景独立存在

之后的学习中我们会进一步体会到层的作用

Cocos2d-x入门之旅[4]场景的更多相关文章

  1. Cocos2d-x入门之旅[1]场景

    在游戏开发过程中,你可能需要一个主菜单,几个关卡和一个END的界面,如何组织管理这些东西呢? 和其他游戏引擎类似,Cocos也使用了场景(Scene) 这个概念 试想象一部电影或是番剧,你不难发现它是 ...

  2. Swift语言入门之旅

    Swift语言入门之旅  学习一门新的计算机语言,传统来说都是从编写一个在屏幕上打印"Hello world"的程序開始的.那在 Swift,我们使用一句话来实现它: printl ...

  3. cocos2d基础入门

    HelloCpp中Classes目录下放开发者自己的类: win32:平台相关,coco2d已默认创建:coco2d-x目录下,samples/cpp/HelloCpp/(工程根目录)图片放置位置:根 ...

  4. nginx入门系列之应用场景介绍

    目录 HTTP服务器 反向代理服务器 作为一个虚拟主机下多个应用的反向代理 作为多个虚拟主机的反向代理 负载均衡器 简单轮训策略 最小连接数策略 客户端IP哈希策略 服务器权重策略 邮件代理服务器 官 ...

  5. Cocos2d-x入门之旅[2]精灵

    精灵就是cocos是屏幕上移动的对象,能被我们控制,比如我们HelloWorld场景的这个图片就是精灵(Sprite) 怎么才算精灵?你能控制它的,就是一个精灵,否则就只是一个节点(Node) 准确的 ...

  6. Cocos2d-x入门之旅[3]动作

    Cocos通过动作(Action)可以让精灵动起来,把数个动作组成序列(Sequence)就能让精灵做出连续的动作,在动作中我们可以改变精灵的位置,旋转角度,缩放比例,等等 动作(Action) 首先 ...

  7. Cocos2d-x入门之旅

    Cocos通过动作(Action)让精灵动起来,把数个动作组成序列(Sequence)就能让精灵做出连续的动作,在动作中我们可以改变精灵的位置,旋转角度,缩放比例,等等 动作(Action)# 首先我 ...

  8. IOS-swift5.1快速入门之旅

    快速之旅 传统表明,新语言中的第一个程序应在屏幕上打印“Hello,world!”字样.在Swift中,这可以在一行中完成: print("Hello, world!") // P ...

  9. 云原生 - 体验Istio的完美入门之旅(一)

    作者:justmine 头条号:大数据达摩院 微信公众号:大数据处理系统 创作不易,在满足创作共用版权协议的基础上可以转载,但请以超链接形式注明出处. 为了方便大家阅读,可以关注头条号或微信公众号,后 ...

随机推荐

  1. Codeforces Round #585 (Div. 2)

    https://www.cnblogs.com/31415926535x/p/11553164.html 感觉很硬核啊这场,,越往后越做不动,,,emmmm,,,(这场是奔着最后一题 2sat 来的, ...

  2. jmeter性能分析

    1.硬件要求:包括客户端和服务端的cpu,mem,network,disk等,这些硬件设备必须满足性能测试的前提下,才能进行性能测试,否则得到的各项指标不一定是正确的 2.场景分析: 测试前的准备工作 ...

  3. Day20 磁盘管理2之RAID卡

    1.磁盘的基本分区Gdisk 前面我们已经了解到fdisk分区,但fdisk不支持给高于2TB的磁盘进行分区.如果有单块盘高于2TB,建议使用Gdisk进行分区. 1.使用gdisk进行磁盘分区 1. ...

  4. 百度脑图-离线版(支持Linux、Mac、Win)

    免费好用的思维导图软件(在线版) 离线版:桌面版脑图是基于百度脑图的本地化版本,帮助你在没有互联网环境的情况下,依然可以使用脑图工具. 百度脑图帮助你进行思维导图,可以运用于学习.写作.沟通.演讲.管 ...

  5. [Code] 烧脑之算法模型

    把博客的算法过一遍,我的天呐多得很,爱咋咋地! 未来可考虑下博弈算法. 基本的编程陷阱:[c++] 面试题之犄角旮旯 第壹章[有必要添加Python] 基本的算法思想:[Algorithm] 面试题之 ...

  6. 使用 Fabric 自动化部署 Django 项目

    作者:HelloGitHub-追梦人物 文中涉及的示例代码,已同步更新到 HelloGitHub-Team 仓库 在上一篇教程中,我们通过手工方式将代码部署到了服务器.整个过程涉及到十几条命令,输了 ...

  7. 转:查看oracle数据库允许的最大连接数和当前连接数

    在查看数据的连接情况很有用,写完程序一边测试代码一边查看数据库连接的释放情况有助于分析优化出一个健壮的系统程序来. 1.查看当前的数据库连接数 select count(*) from v$proce ...

  8. 接口测试返回数据为JSONP格式时如何处理

    #需要被处理的jsonp数据 JSONP = "jsonpreturn({'c': 1, 'd': 2});" #处理方法 def jsonp_to_json(JSONP): JS ...

  9. 使用.net core3.0 正式版创建Winform程序

    前阵子一直期待.net core3.0正式版本的出来,以为这个版本出来,Winform程序又迎来一次新生了,不过9.23日出来的马上下载更新VS,创建新的.net core Winform项目,发现并 ...

  10. 调试 内存查看StringCchCopy的运行前后

    // ConsoleApplication1.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" int _tmain(int argc, _T ...