我们之前讲了场景图(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. ExpandableListView之BaseExpandableListAdapter

    之前使用的SimpleExpandableListAdapter有较大局限性,样式单一,修改难度大,这里不建议使用,而是利用BaseExpandableListAdapter,其实SimpleExpa ...

  2. celery详解

    目录 Celery详解 1.背景 2.形象比喻 3.celery具体介绍 3.1 Broker 3.2 Backend 4.使用 4.1 celery架构 4.2 安装redis+celery 4.3 ...

  3. vscode主题安装

    安装主题 快捷键Ctrl+Shift+X打开安装插件 搜索Monokai ST3 切换主题 显示效果 安装文件图标 扩展插件vscode-icon 鼠标滚轮设置字体大小 打开setting.json文 ...

  4. Python学习-字符编码, 数据类型

    本篇主要内容: 字符编码 Python中的数据类型有哪些 类型的一些常用操作及方法 一.字符编码 编码解释的大部分内容摘自廖雪峰老师教程中的讲解,点击跳转. 简单介绍: 我们知道计算机只能处理数字,如 ...

  5. Java异常详谈

    什么是异常: 异常(Exception)是程序运行过程中发生的事件,该事件可以中断程序指令的正常执行流程. 注意: 如果实际抛出的异常对象属于Exception的子类对象,而继承自Throwable类 ...

  6. JDBC对Mysql utf8mb4字符集的处理

    写在前面 在开发微信小程序的时候,评论服务模块希望添加上emoji表情,但是emoji表情是4个字节长度的,所以需要进行设置 当前项目是JAVA编写, 使用JDBC连接操作数据库, 如下针对的JDBC ...

  7. 数据结构与算法(C/C++版)【排序】

    第八章<排序>  一.直接插入排序  //直接插入排序 //算法思想:每趟将一个待排的关键字按照其值的大小插入到已经排好的部分有序序列的适当位置上,直到所有待排关键字都被插入到有序序列中为 ...

  8. hihttps教你在Wireshark中提取旁路https解密源码

    大家好,我是hihttps,专注SSL web安全研究,今天本文就是教大家怎样从wireshark源码中,提取旁路https解密的源码,非常值得学习和商业应用. 一.旁路https解密条件 众所周知, ...

  9. spring系列常用注解

    常见注解使用 - @SpringBootApplication,springboot的核心注解,用于开启自动配置,等效于@Configuraion.@ComponentScan和@EnableAuto ...

  10. LINUX系统学习以及初学者系统下载

    Linux系统常用命令大全 来源:服务器之家 [博客中所有文章如有不对的地方希望看官们指出,有问题也可以提出来相互交流,相互学习,感谢大家!] 初学者建议安装:sentOS Ubuntu系统下载连接h ...