在上一篇中,使用CCSprite和CCMenu構建了開始場景,並且說明了關於優化程序內容的問題,一個好的游戲會有很多的場景場景組合,每個場景管理自身的腳本也就是規則,在整個游戲中是如何跳轉場景的呢?先看下圖:
本圖來自Elvis的CCDirector類解析配圖,先不用看太全面,只需要看最上面的就行了,前面說過,整個游戲有一個導演(CCDirector)在管理整個場景,為了讓切換場景完成的更好,需要按照之前的場景制作方法將其他的場景補齊,即例如關卡選擇界面、游戲界面、游戲結束界面的完成。
完成全部的場景 |
在制作前需要生成圖片資源
上面的資源中,包含了基本場景的元素,和一張用來演示游戲界面的示意圖,打開TexturePackerGUI,將它們組合,由於有幾張比較大的圖,制作的時候看看是否有浪費,也可以將它們分成多個plist,比如說,我這次將一定會用上的圖片打包到GameUI01.plist,而預覽圖就打包到了GameUI02.plist中,將它們添加到Content里:
好了,現在有了兩個資源plist,GameUI01在SceneStart類中載入過,為了保證資源載入的統一性,建立一個GameRoot的類,並用靜態的方法取得,不要忘記將SceneStart里的addSpriteFramesWithFile刪除:
public class GameRoot { public static void InitializeResource() { CCSpriteFrameCache.sharedSpriteFrameCache().addSpriteFramesWithFile("GameUI01", "images/GameUI01"); CCSpriteFrameCache.sharedSpriteFrameCache().addSpriteFramesWithFile("GameUI02", "images/GameUI02"); } }
注意要把GameRoot.InitializeResource();添加到AppDelegate.cs的applicationDidFinishLaunching函數中,注意要添加到場景跳轉的前面一行,這樣場景在構建的時候就會先載入了圖片資源。
也許有更好的方案,比如放在一個Loading界面里面,在這里GameRoot還有其他的作用,就如它的名字當成游戲根來處理,我們可以在這里將所有的場景集合管理,采用單例的方式完成全局的控制訪問,我們可以這樣做:
//通過一個全局的根來管理整個游戲的所有場景實例 public class GameRoot { public static void InitializeResource() { CCSpriteFrameCache.sharedSpriteFrameCache().addSpriteFramesWithFile("GameUI01", "images/GameUI01"); CCSpriteFrameCache.sharedSpriteFrameCache().addSpriteFramesWithFile("GameUI02", "images/GameUI02"); } private static SceneStart _SceneStart; public static SceneStart pSceneStart { get { if (_SceneStart == null) _SceneStart = new SceneStart(); return _SceneStart; } } private static SceneSelect _SceneSelect; public static SceneSelect pSceneSelect { get { if (_SceneSelect == null) _SceneSelect = new SceneSelect(); return _SceneSelect; } } private static SceneGame _SceneGame; public static SceneGame pSceneGame { get { if (_SceneGame == null) _SceneGame = new SceneGame(); return _SceneGame; } } private static SceneOver _SceneOver; public static SceneOver pSceneOver { get { if (_SceneOver == null) _SceneOver = new SceneOver(); return _SceneOver; } } }
由於比較長,給折疊了,在這里可以保證唯一的單例完成統一管理,在游戲的任何地方,都可以呼喚GameRoot取得場景實例了。
下面是SceneSelect類的代碼,選擇界面如果想做的復雜的話就得這么搞了,當然這樣也更有趣,本篇該類代碼只是實現了基本功能,未來在用到CCAction類的時候將它做到更完美:
public class SceneSelect : CCScene { public SceneSelect() { base.init(); //背景圖 CCSprite background = CCSprite.spriteWithSpriteFrameName("bg_select.png"); background.anchorPoint = new CCPoint(0, 0); this.addChild(background); CCMenuItemSprite btn_back = CCMenuItemSprite.itemFromNormalSprite( CCSprite.spriteWithSpriteFrameName("btn_back1.png"), CCSprite.spriteWithSpriteFrameName("btn_back2.png"), this, click_back); CCMenu menu = CCMenu.menuWithItems(btn_back); menu.position = new CCPoint(666,32); this.addChild(menu); CCSprite tab1 = CCSprite.spriteWithSpriteFrameName("tab_shu1.png"); CCSprite tab2 = CCSprite.spriteWithSpriteFrameName("tab_wu2.png"); CCSprite tab3 = CCSprite.spriteWithSpriteFrameName("tab_wei2.png"); tab1.position = new CCPoint(115, 430); tab2.position = new CCPoint(335, 430); tab3.position = new CCPoint(575, 430); this.addChild(tab1); this.addChild(tab2); this.addChild(tab3); CCPoint offset = new CCPoint(150, 150); for (int i = 0; i < 4; i++) { for (int j = 0; j < 3; j++) { CCMenuItemSprite level = CCMenuItemSprite.itemFromNormalSprite( CCSprite.spriteWithSpriteFrameName("btn_level1.png"), CCSprite.spriteWithSpriteFrameName("btn_level2.png"), this, click_level); menu = CCMenu.menuWithItems(level); menu.position = new CCPoint(offset.x + 160 * i,offset.y + 85 * j); this.addChild(menu); } } } private void click_back(CCObject s) { } private void click_level(CCObject sender) { } }
場景選擇的實現效果:
選擇關卡的場景里,全部都跳轉到SceneGame中,以后將對應的關卡進行設計。
下面是游戲場景SceneGame的代碼,這里的Code只是貼了一張圖,然后加了一個“出征”按鈕,這個出征按鈕在本例中將做成游戲結束的觸發器:
public class SceneGame : CCScene { public SceneGame() { base.init(); //背景圖 CCSprite background = CCSprite.spriteWithSpriteFrameName("bg_game.png"); background.anchorPoint = new CCPoint(0, 0); this.addChild(background); //返回按鈕 CCMenuItemSprite btn_attack = CCMenuItemSprite.itemFromNormalSprite( CCSprite.spriteWithSpriteFrameName("btn_soldierattack1.png"), CCSprite.spriteWithSpriteFrameName("btn_soldierattack2.png"), this, click_attack); CCMenu menu = CCMenu.menuWithItems(btn_attack); menu.position = new CCPoint(732, 36); this.addChild(menu); } private void click_attack(CCObject sender) {} }
代碼效果如下:
最后一個是結束場景:
public class SceneOver : CCScene { public SceneOver() { base.init(); //背景圖 CCSprite background = CCSprite.spriteWithSpriteFrameName("bg_over.png"); background.anchorPoint = new CCPoint(0, 0); this.addChild(background); //文字 CCSprite title = CCSprite.spriteWithSpriteFrameName("text_over.png"); title.position = new CCPoint(CCDirector.sharedDirector().getWinSize().width / 2, CCDirector.sharedDirector().getWinSize().height / 2 + 150); this.addChild(title); //返回按鈕 CCMenuItemSprite btn_back = CCMenuItemSprite.itemFromNormalSprite( CCSprite.spriteWithSpriteFrameName("btn_back1.png"), CCSprite.spriteWithSpriteFrameName("btn_back2.png"), this, click_back); CCMenu menu = CCMenu.menuWithItems(btn_back); menu.position = new CCPoint(666, 32); this.addChild(menu); } private void click_back(CCObject s) {} }
效果如下:
場景切換 Transition |
好了, 我們現在完成了基本的場景,現在要進行場景的切換操作,下面將會用上三個CCDirector類方法:
popScene() : 返回到上一個場景
pushScene(CCScene pScene) :切換到一個指定的場景
replaceScene(CCScene pScene) :替換掉當前的場景
在CCDirector中場景管理是一個隊列,寫說明還是比較麻煩,下面畫張圖來表示一下:
如圖示意,場景隊列內部已經幫你管理好了,所以不用考慮太多。
那么在代碼中如何體現呢?只需要對對應的委托事件進行處理就行了,例如在開始界面點擊“開始”就會pushScene到SceneSelect場景,而點擊返回則執行popScene,replaceScene就很簡單了,用於在游戲結束的時將SceneGame替換成為SceneOver。
所添加的代碼如下:
SceneStart:
private void click_start(CCObject sender) { CCDirector.sharedDirector().pushScene(GameRoot.pSceneSelect); }
SceneSelect:
private void click_back(CCObject s) { CCDirector.sharedDirector().popScene(); } private void click_level(CCObject sender) { CCDirector.sharedDirector().pushScene(GameRoot.pSceneGame); }
SceneGame:
private void click_attack(CCObject sender) { CCDirector.sharedDirector().replaceScene(GameRoot.pSceneOver); }
SceneOver:
private void click_back(CCObject s) { CCDirector.sharedDirector().popScene(); }
現在運行一下效果,點擊按鈕看切換。
轉場效果 Effect |
最后說一說,轉場的效果,點擊直接變化是不是顯得非常的單調?更加絢麗的轉場效果在引擎中已經提供了,可以看cocos2d-xna代碼中的transition部分,幾十個切換效果任由選擇:
具體的用法非常簡單,例如我們在開始界面點擊“開始”按鈕的時候,進行一個CCTransitionFade轉場效果,這個效果可以讓屏幕一黑,然后變成新的場景,在SceneStart.cs中click_start方法里加入如下代碼:
private void click_start(CCObject sender) { var s = CCTransitionFade.transitionWithDuration(0.5f, GameRoot.pSceneSelect); CCDirector.sharedDirector().pushScene(s); }
這種一般情況下要折騰很久的切換效果,在引擎里只是一行代碼而已,不同的Transition有不同的參數,有興趣的朋友可以參看OpenXLive移植的cocos2d-xna里的test工程樣本,里面展示了非常多的切場效果,在這里就不再太多的演示了。
本篇例子工程:https://github.com/Nowpaper/SanguoCommander_cocos2dxna_Sample
本例工程名為:SanguoCommander3
本篇主要講述了場景的深度制作和Transition用法,主要是對場景Scene內容,下篇中將使用CCLayer,還會結合CCAction完成復雜的界面互動編寫。