ibcadmin 发表于 2019-10-24 09:49:35

Cocos2d-x入门之旅[4]场景

<p>我们之前讲了场景图(Scene Graph) 的概念,继续之前你先要知道</p>
<ul>
<li>场景图决定了场景内节点对象的渲染次序</li>
<li>渲染时 <strong>z-order</strong> 值大的节点对象会后绘制,<strong>值小的节点对象先绘制</strong></li>
</ul>
<h2 id="helloworld">HelloWorld</h2>
<p>你还记得HelloWorld场景是如何启动的么?回看我们工程里的<strong>AppDelegate.cpp</strong>,滚到<code>applicationDidFinishLaunching()</code>的尾部:</p>
<code>// create a scene. it&#39;s an autorelease object
auto helloWorldscene = HelloWorld::createScene();
// run
director->runWithScene(helloWorldscene);</code>
<p>Ctrl+鼠标左键 点选<code>createScene()</code>查看界说,可以看到这个函数在HelloWorldScnen.h内声明,在HelloWorldScnen.cpp内界说</p>
<code>// HelloWorldScnen.h
static cocos2d::Scene* createScene();

// HelloWorldScnen.cpp
Scene* HelloWorld::createScene()
{
    return HelloWorld::create();
}</code>
<p>我们可以通过该函数获取一个HelloWorld场景对象</p>
<p>之后就是场景的初始化,菜单,精灵等对象的Set都在这里进行</p>
<code>bool HelloWorld::init()
{
    ...
}</code>
<p>末了我们看到一个回调函数</p>
<code>void HelloWorld::menuCloseCallback(Ref* pSender)
{
    //Close the cocos2d-x game scene and quit the application
    Director::getInstance()->end();
}</code>
<p>C++底子差的同砚可能还不理解回调的概念,但你只必要知道,这个函数实现了:HelloWorld场景内点击关闭按可钮关闭窗口 的功能,就行了、</p>
<h2 id="secondscene">SecondScene</h2>
<p>如今我们对着HelloWorld的代码来创建一个SecondScene</p>
<p>和HelloWorld一样,起首我们必要一份<strong>SecondScene.h</strong>存放声明,然后是一份<strong>SecondScene.cpp</strong>存放界说</p>
<blockquote>
<p>留意VS内新建文件时,肯定要保存到<strong>Class</strong>文件夹内,不然你是不能直接include“xxxxxx”的(万恶的VS默认保存路径不是<strong>Class</strong>)</p>
<p><div align="center"></div></p>
<p>修改到项目目次下的<strong>Class</strong></p>
<p><div align="center"></div></p>
</blockquote>
<h3 id="secondscene.h">SecondScene.h</h3>
<p>起首是套一层宏掩护到头尾</p>
<code>#ifndef __SECOND_SCENE_H__
#define __SECOND_SCENE_H__

#endif // __SECOND_SCENE_H__</code>
<p>然后</p>
<code>#include "cocos2d.h"</code>
<p>如今我开始我们要做一点点小变化,我们让SecondScene继续Layer而不是Scene</p>
<code>class SecondScene : public cocos2d::Layer {
public:
    static cocos2d::Scene* createScene();
    virtual bool init();
    CREATE_FUNC(SecondScene);
    //暂时不必要回调函数
};</code>
<blockquote>
<p>实际上之前的cocos实例工程里HelloWorld都是继续自Layer的,不知为何如今改了,但是无妨,我们借此时机介绍Layer和Scene的区别</p>
</blockquote>
<h3 id="secondscene.cpp">SecondScene.cpp</h3>
<p>起主要include我们之前写好的SecondScene.h,为了方便我们也和HelloWorld一样<code>using namespace cocos2d</code></p>
<blockquote>
<p>你可能看到了HelloWorld.cpp里写的是<code>USING_NS_CC</code>而不是<code>using namespace cocos2d</code>,但着实效果是一样的</p>
<p><div align="center"></div></p>
</blockquote>
<p>接下来我们界说creatSceen()函数,也和HelloWorld::createScene()略有不同</p>
<code>Scene* SecondScene::createScene() {
    //创建一个Scene类的对象scene
    auto scene = Scene::create();
    //创建一个SecondScene类的对象layer
    auto SecondScene = SecondScene::create();
    //把layer添加到scene里
    scene->addChild(layer);
    //返回scene
    return scene;
}</code>
<p>理解起来很简朴:起首我们创建了一个Scene类的对象scene,然后创建了一个SecondScene类的对象layer(别忘了我们的SecondScene继续自layer),再把layer添加到了scene里,末了返回我们的scene</p>
<p>之后就可以开始写初始化函数了</p>
<code>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;
}
</code>
<p>我们不消加太多东西,加入一个label让自己知道这是SecondScene场景就行</p>
<p>如今我们去步伐的入口,<strong>AppDelegate.cpp</strong>里看看,还记得启动HelloWorld场景的那两行代码么,我们改成启动SecondScene场景:</p>
<p>(记得先要加入<code>#include "SecondScene.h"</code>到AppDelegate.cpp里)</p>
<code>// create a scene. it&#39;s an autorelease object
auto helloWorldscene = HelloWorld::createScene();
// run
director->runWithScene(helloWorldscene);
</code>
<p>改成</p>
<code>auto secondScene = SecondScene::createScene();
director->runWithScene(secondScene);
</code>
<p>运行测试:</p>
<p><div align="center"></div></p>
<p>没有问题</p>
<h2 id="场景切换">场景切换</h2>
<p>接下来我们把<strong>AppDelegate.cpp</strong>还原归去(Crtl+Z),让步伐运行时还是从HelloWorld场景开始,然后实验使用回调函数切换到SecondScene</p>
<p>由于我们要在HelloWorld切换到Second,以是我们必要在HelloWorld场景里添加一个回调变乱,刚好HelloWolrd里就有一个关闭按钮的回调,我们改改代码就行(这里重点是演示如何切换,真的不是我懒)</p>
<p>追踪到<code>HelloWorld::menuCloseCallback()</code>:</p>
<p>把<code>Director::getInstance()->END</code>改成</p>
<code>Director::getInstance()->replaceScene(
    SecondScene::createScene()
);
</code>
<p>运行测试,不出意外再点击HelloWorld右下角的关闭按钮,就会一刹时切换到Second</p>
<h3 id="切换动画">切换动画</h3>
<p>Cocos内置了许多切换场景的动画,比如</p>
<code>Director::getInstance()->replaceScene(
    TransitionSlideInT::create(
      3.0f, SecondScene::createScene()
    )
);
</code>
<p>运行,Second会在3秒内从上平滑切换掉HelloWorld</p>
<p>别的切换动画就不赘述了,和Actions又异曲同工之妙,各自己试试吧</p>
<h3 id="场景栈">场景栈</h3>
<p>我们之前都是在使用replaceScene进行场景切换,replaceScene会使前一个场景被开释(简朴来说就是删掉了,不再占用内存,想找回来只能重新创建一个),节省了内存资源,但有时我们不希望场景被开释怎么办呢</p>
<p>Cocos还提供了 推进<code>pushScene()</code>和弹出<code>popScene</code>两种方法,把一系列场景存储到栈内,按需弹出(开释)和推进新场景</p>
<blockquote>
<p><strong>栈</strong>是一种数据结构,你可以简朴理解为一个弹匣,对栈有两种操作:</p>
<ol>
<li><strong>入栈(push)</strong>,装入子弹</li>
<li><strong>出栈(pop)</strong>,射出子弹</li>
</ol>
<p>子弹总是最上面的先被射出(pop时栈顶的元素开始出栈),也就是<strong>“先进后出”</strong></p>
</blockquote>
<p>新加入场景时使用<code>pushScene()</code>,新旧场景就会被存入场景栈,新在上旧在下(也就是说旧的场景没有开释),<code>popScene</code>会将新的场景开释,旧的场景就被弹了上来原来的位子,表现旧场景</p>
<p>你可以在场景初始化函数内写一段期待x秒的代码(换个思绪,可以写一个计时器),验证pop后表现的旧场景不是新创建的:</p>
<code>bool HelloWorld::init()
{
    ...
      
    for(int i = 0; i <19999999; i++)// 耗时操作   
      
    ...
}
</code>
<p>发挥你的奇思妙想,另有什么方法,自己实验一下</p>
<h2 id="层和场景">层和场景</h2>
<p>这个好理解,想想你玩过的2d游戏,或者Photoshop的图层界面,一个场景里可以有好几个层</p>
<p>场景内创建层很简朴:</p>
<code>Layer* layer2 = Layer::create();
</code>
<p>当然一个层必须添加到场景内才会见效,<strong>层无法离开场景独立存在</strong></p>
<p>之后的学习中我们会进一步领会到层的作用</p><br><br/><br/><br/><br/><br/>来源:<a href="https://www.cnblogs.com/zhxmdefj/p/11727785.html" target="_blank">https://www.cnblogs.com/zhxmdefj/p/11727785.html</a>
页: [1]
查看完整版本: Cocos2d-x入门之旅[4]场景