cocos2dx 3.1從零學習(二)——菜單、場景切換、場景傳值

回顧一下上一篇的內容我們已經學會了創建一個新的場景scene,添加spritelabel到層中掌握了定時事件schedule。我們可以順利的寫出打飛機的主場景框架

上一篇的內容我練習了七個新場景每一個場景都展示不同的東西像背景定時切換各種字體的隨機顏色和位置等每次要切換一個場景都要修改AppDelegate中的調用代碼非常的不方便查看這一篇我們寫場景的切換每當我們創建一個新的場景的時候只要添加對應按鈕到主界面點擊即可以切換過去查看對應的效果這個有點類似官方提供的cpptest的查看方式所以說場景切換是非常簡單易用的功能

 

要點擊切換場景必須要有按鈕可以接收消息所以首先學習一下菜單Menu):

Menu創建菜單

MenuItem Create 菜單子項的創建

MenuItemFont是字菜子項

  1. auto item= MenuItemFont::create("Hello,Menu",CC_CALLBACK_1(MenuScene::Menutest, this));  

"Hello, Menu"是菜單子項按鈕的文字

MenuScene::Menutest是回調函數它的參數是Menutest(Ref * pSender)這個參數類型是什麼可以通過查看create定義來獲得

CC_CALLBACK_1就是綁定一個函數爲回調函數_1表示這個函數的只有一個參數

 

我們的第一個菜單可以這樣寫

  1. //開頭這四句肯定是添加到init()函數裏的  
  2. auto item= MenuItemFont::create("Hello,Menu",CC_CALLBACK_1(MenuScene::Menutest, this));  
  3. auto menu= Menu::create();  
  4. menu->addchild(item);  
  5. this->addchild(menu);  
  6.    
  7. voidMenuScene::Menutest(Ref *ref){  
  8. //此處可以添加一個精靈,每點擊一次菜單按鈕就添加一個精靈到場景中。  
  9. }  

還可以這樣創建一個菜單不必每次都調用menu->addchild(item):

  1.  auto item =MenuItemFont::create("Hello, Menu",CC_CALLBACK_1(MenuScene::Menutest,this));  
  2.  auto item1 =MenuItemFont::create("Ruck, Menu",CC_CALLBACK_1(MenuScene::Menutest1, this));  
  3.  auto item2 =MenuItemFont::create("Click, Menu",CC_CALLBACK_1(MenuScene::Menutest2, this));  
  4.  auto item3 =MenuItemFont::create("KTWork", CC_CALLBACK_1(MenuScene::KTWork,this));  
  5.  auto item4 =MenuItemFont::create("PushScene", CC_CALLBACK_1(MenuScene::PushScene,this));  
  6.  auto item5 =MenuItemFont::create("HomeWork", CC_CALLBACK_1(MenuScene::HomeWork,this));  
  7.  auto item6 =MenuItemFont::create("HomeWork0617",CC_CALLBACK_1(MenuScene::HomeWorkSnow, this));  
  8.  auto item7 =MenuItemFont::create("KT0618", CC_CALLBACK_1(MenuScene::KT0618,this));  
  9.   
  10.  auto menu =Menu::create(item, item1, item2, item3, item4, item5 ,item6,item7,<span style="color:#ff0000;">NULL);//注意最後一個參數爲空</span>  
  11. menu->setPosition(Director::getInstance()->getVisibleSize().width/ 2,Director::getInstance()->getVisibleSize().height / 2);  
  12. menu->alignItemsVerticallyWithPadding(40);//看英文就知道是垂直對齊  間隔40像素  
  13. his->addchild(menu);  

在回調函數中操作菜單子項的屬性

voidMenuScene::Menutest1(Ref *ref){

   MenuItemFont *item =(MenuItemFont *)ref;//所有的類的基類Ref,我們在菜單中是通過MenuItemFont創建的item,所以在回調函數中可以強制轉換回MenuItemFont類型然後就可以在回調函數中修改菜單子項的屬性了

  1.     if (item->getColor() == Color3B::RED)  
  2.     {  
  3.         item->setColor(Color3B::GREEN);  
  4.         item->setFontSizeObj(55);  
  5.        item->setFontNameObj("Baskerville-Boldltalic");  
  6.        item->setString("GreenClick");  
  7.     }  
  8.     else  
  9.     {  
  10.         item->setColor(Color3B::RED);  
  11.         item->setFontSizeObj(24);  
  12.        item->setFontName("Baskerville-Boldltalic");  
  13.        item->setString("RedClick");  
  14.     }  
  15. }  

從上面代碼可以看到我創建了一個菜單裏面有很多子項這些子項都是場景切換每一個新的場景都是一個練習

見效果圖:


 

關於創建菜單子項還有很多方法

MenuItemLabelMenuItemImageMenuItemSprite

下面拿MenuItemLabel舉例futura-48.fnt在我第一篇打飛機源碼的素材裏源碼在一樓,這種字體除了fnt還有一個png文件,是一起的,不能分開。這種字體創建的菜單就是下圖中黃色的效果。

autoitem2 =MenuItemLabel::create(Label::createWithBMFont("fonts/futura-48.fnt","Start"), CC_CALLBACK_1(MenuSceneTwo::MenuTest, this));

具體的效果圖看下面:

這是我的第一個Hello,Menu場景



上面已經介紹了菜單的創建,嘗試這去創建一個新場景吧,點擊按鈕可以切換不同的背景。

給菜單子項綁定數據

在這裏還要學習菜單子項item的兩個操作函數。setUserData和setUserObject。

setUserData看定義接收的是void*參數,可以接收任意類型的數據。我們可以用它來傳遞C++的基本類型數據,但是千萬不要自己new一些變量來傳值,會造成意外的。

setUserObject接收的是繼承自Ref的子類。繼承自Ref的子類,最常用的就是cocos2dx本身的String了。

  1. auto item1 = MenuItemLabel::create(Label::createWithBMFont("fonts/futura-48.fnt""Easy"), CC_CALLBACK_1(HomeWorkSnow::Start, this));  
  2. item1->setUserObject(String::create("Easy"));  
  3. auto item2 = MenuItemLabel::create(Label::createWithBMFont("fonts/futura-48.fnt""Hard"), CC_CALLBACK_1(HomeWorkSnow::Start, this));  
  4. item2->setUserObject(String::create("Hard"));  
  5. auto item3 = MenuItemLabel::create(Label::createWithBMFont("fonts/futura-48.fnt""Difficult"), CC_CALLBACK_1(HomeWorkSnow::Start, this));  
  6. item3->setUserObject(String::create("Difficult"));  
  7. auto item4 = MenuItemLabel::create(Label::createWithBMFont("fonts/futura-48.fnt""Hell"), CC_CALLBACK_1(HomeWorkSnow::Start, this));  
  8. item4->setUserObject(String::create("Hell"));  
  9. auto menu = Menu::create(item1, item2, item3, item4, NULL);  
  10. addChild(menu);  
  11. menu->alignItemsVertically();  

我們要把set的數據取出來,對應的兩個函數是getUserData和getUserObject。

在菜單響應回調函數中,我們可以如下操作:

  1. void  HomeWorkSnow::Start(Ref *ref)  
  2. {  
  3.     MenuItemLabel *item = (MenuItemLabel*)ref;  
  4.     String * str = (String *)item->getUserObject();  
  5.   
  6.     auto scene = HomeWorkSnowFight::createScene();  
  7.     HomeWorkSnowFight *layer = (HomeWorkSnowFight*)scene->getChildren().at(0);  
  8.   
  9.     layer->setData(mode[str->getCString()]);  
  10.     Director::getInstance()->pushScene(TransitionCrossFade::create(1, scene));  
  11.   
  12. }  

第一步是強轉,我們用什麼類型創建的item,在回調裏我們就使用對應的類型強轉回來。然後調用item的getUserObjet獲取set的值。

後面三句是場景的正向傳值,這個會在本篇最後講到。提前提一下,就是調用下個場景層對象的成員函數做到傳道的。


***********************************************************************************************************************************

切換場景

再創建一個新場景然後使用下面語句添加到菜單回調函數來切換場景

  1. auto scene =KTWork_SwitchBg::createScene();  
  2. Director::getInstance()->replaceScene(scene);  

這樣我們就實現了從一個場景切換到另一個場景

我們可以在另一個場景中盡情的添加想要的精靈你也可以嘗試把昨天創建的打飛機的場景添加進來點擊菜單按鈕就可以開始打飛機了

 

切換場景動畫

如果要使用切換的特效動畫如下修改即可

  1. auto scene =KTWork_SwitchBg::createScene();  
  2. Director::getInstance()->replaceScene(TransitionPageTurn::create(1,scene,true));  


還有(TransitionShrinkGrow::create(1,scene)); (TransitionCrossFade::create(1, scene));

請多嘗試幾種特效方法Transition******::create()

 

如果你想返回主菜單只需要在子場景中添加一個返回的按鈕即可聰明的你肯定能想到怎麼返回主菜單


細心的話會發現切換場景的時候會提示有兩個切換方式,一種是replacescene,一種是pushscene。這兩種切換方式的區別在於,前者釋放了當前場景,後者把當前場景壓入棧中保存。pushscene的場景要切換回來,只需在子場景中調用popscene即可。 相當於原來的場景暫停了一會。

************************************************************************************************************

場景傳值

正向傳值

我們在切換場景之前向下一個場景傳遞參數這個是正向傳值

最簡單的方法就是給下一個場景的類成員變量賦值 這樣我們就能在主場景控制我們在下一個場景想要展示的屬性

 

如下回調函數我們返回的場景獲取場景中所有的子節點請右鍵查看getChildren的返回值因爲子場景中只有一個節點所以我們第一個元素肯定是層也就是 KTWork_PushScene類對象然後我們可以使用tmp來任意正向傳遞參數給下個場景

  1. voidMenuScene::PushScene(Ref *ref){  
  2.     this->stopAllActions();  
  3.     auto scene =KTWork_PushScene::createScene();  
  4.     <span style="color:#ff0000;">KTWork_PushScene * tmp = (KTWork_PushScene*)(scene->getChildren().at(0));</span>  
  5.    Director::getInstance()->pushScene(TransitionShrinkGrow::create(1,scene));  
  6. }  

注意我們在傳遞參數之前KTWork_PushScene已經調用過init()函數初始化完畢那我們應該怎麼使傳遞的值生效呢答案是使用虛函數onEnter()。onEnter是在切換場景後展示場景前調用所以我們可以如下修改代碼

  1. voidHomeWork::onEnter()  
  2. {  
  3.    <span style="color:#ff0000;"> Layer::onEnter(); //一定要先調用父類onEnter方法</span>  
  4.    label->setString(StringUtils::format("%s",strHp.getCString()));//這樣我們就動態修改了Label展示的值  
  5. }  
  6.    

在類中我們通常設變量爲私有通過get、set方法來對其訪問cocos2dx有一個宏可以替代我們定義這兩個方法的操作

  1.  CC_SYNTHESIZE(int, hp, HP);//定義了一個protected變量hp,定義了兩個方法setHP,getHP來獲取和設置hp的值。  
  2.  CC_SYNTHESIZE(String, strHp, sHP);  
  3. CC_SYNTHESIZE_RETAIN(__String *, strname, Name);//這個針對於指針變量。你現在使用可能會有崩潰的地方,這個在後面的內存管理會詳細講。這個宏定義沒有想象的那麼簡單,提醒一下,要修改類的構造和析構函數。  

這兩個宏大家一定要自己去看一下是如何定義的

 


總結:我們學習了菜單,觸控響應,切換場景等,現在可以做一個 如下的遊戲了。

有四種遊戲模式,天空會降落雪花,每一種模式雪花大小不同。 鼠標點擊可以使雪花小時。遊戲結束返回主場景。

效果如下:





遊戲代碼我放到一樓去。 這些代碼我後期也在優化。可能有一些知識點還沒有涉及到。大家可以用一下素材。

可能會看到我主場景有飄雪花的特效,一些煙火特效。這些都是我複製別人的代碼實現的,有興趣的可以自己看一下,很簡單。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章