我們之前講了場景圖(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兩種方法,把一系列場景存盤到堆疊內,按需彈出(釋放)和推進新場景
堆疊是一種資料結構,你可以簡單理解為一個彈匣,對堆疊有兩種操作:
- 入堆疊(push),裝入子彈
- 出堆疊(pop),射出子彈
子彈總是最上面的先被射出(pop時堆疊頂的元素最先出堆疊),也就是“先進后出”
新加入場景時使用pushScene(),新舊場景就會被存入場景堆疊,新在上舊在下(也就是說舊的場景沒有釋放),popScene會將新的場景釋放,舊的場景就被彈了上來原來的位子,顯示舊場景
你可以在場景初始化函式內寫一段等待x秒的代碼(換個思路,可以寫一個計時器),驗證pop后顯示的舊場景不是新創建的:
bool HelloWorld::init()
{
...
for(int i = 0; i <19999999; i++)// 耗時操作
...
}
發揮你的奇思妙想,還有什么方法,自己實驗一下
層和場景
這個好理解,想想你玩過的2d游戲,或者Photoshop的圖層界面,一個場景里可以有好幾個層
場景內創建層很簡單:
Layer* layer2 = Layer::create();
當然一個層必須添加到場景內才會生效,層無法離開場景獨立存在
之后的學習中我們會進一步體會到層的作用
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/14579.html
標籤:其他
上一篇:lua行為樹設計與實作



