不知道有多少朋友了解動畫和電影的制作手法,他們都是一個場景一個場景的拍攝錄制,然后剪輯成為一部完整的片子,而游戲是非常類似,你可以理解要制作一個世界,然后讓玩家其中按照世界的規則進展,而屏幕就是最好的觀察者,可是好的片子要有一個“指揮”世界運轉,讓主角按照預定的路線行進,這在cocos2d中對應的是導演類(CCDirector),在http://www.cnblogs.com/hielvis/archive/2012/06/05/2534706.html中詮釋的非常清晰,如想深入建議好好讀讀。
現在拿出之前的設計材料,好好想想游戲該有什么場景,在本篇游戲中,將會主要在如下的四個場景切換:
從上圖中可以看出是開始,然后到選擇戰役,再到游戲中,最后為結束,游戲的主體的流程就這么搞定。
開始 第一個場景 |
之前的代碼只是進了一個Test場景,現在咱們做一個新的場景,先將上面的開始界面完成,把圖片的素材准備好,將界面拆分主要有背景圖、按鈕、標志,將圖片保存兵添加到Content里:
下面打開Scenes里的SceneStart.cs,把類寫成下面這樣:
public class SceneStart : CCScene { public SceneStart() { base.init(); //取得屏幕大小 CCSize size = CCDirector.sharedDirector().getWinSize(); //背景圖 CCSprite background = CCSprite.spriteWithFile("bg_start") ; this.addChild(background); //Logo圖 CCSprite logo = CCSprite.spriteWithFile("logo"); //設置到界面中間偏上 logo.position = new CCPoint(size.width / 2, size.height / 2 + 120); this.addChild(logo); //兩個按鈕 CCMenuItemImage btn_start = CCMenuItemImage.itemFromNormalImage("btn_start1", "btn_start2", this, click_start); CCMenuItemImage btn_setting = CCMenuItemImage.itemFromNormalImage("btn_setting1", "btn_setting2", this, click_setting); //MenuItem需要通過CCMenu組合 CCMenu menu = CCMenu.menuWithItems(btn_start, btn_setting); //一個垂直間隔排列 menu.alignItemsVerticallyWithPadding(10); //設置到界面中間偏下 menu.position = new CCPoint(size.width / 2, size.height / 2 - 120); this.addChild(menu); } private void click_start(CCObject sender) { } private void click_setting(CCObject sender) { } }
初步寫完之后可能會需要引用using cocos2d;然后在AppDelegate.cs里面做如下修改:
public class AppDelegate : CCApplication { public AppDelegate(Game game, GraphicsDeviceManager graphics) : base(game, graphics) { CCApplication.sm_pSharedApplication = this; } public override bool applicationDidFinishLaunching() { //初始化CCDirector CCDirector pDirector = CCDirector.sharedDirector(); pDirector.setOpenGLView(); //是否顯示FPS(每秒幀速率) pDirector.DisplayFPS = true;
// 在這里設置Updata的間隔 pDirector.animationInterval = 1.0 / 60; // 創建一個場景 CCScene pScene = new Scenes.SceneStart(); // 運行這個場景 pDirector.runWithScene(pScene); return true; } }
你會發現:CCScene pScene = new Scenes.SceneStart();之后通過pDirector.runWithScene(pScene)進入了這個場景,pDirector就是導演,他說:現在要拍攝開始界面的場景了。
當然里面有很多的布景道具什么的,在上面的代碼中就已經完成,現在運行一下看看:
奇怪,這是為什么會變成這樣呢,這里說一下CCSprite,CCSprite一般叫精靈類,它的主要作用是呈現圖片,在cocos2dxna中沒有專門Image類,一切的圖片就是通過CCSprite來顯示和操作的,CCSprite載入圖片后按照(0.5,0.5)的中心點(也叫錨點anchorPoint)為准,也就是說所在的xy的位置實際為其承載圖片的中心位置,所以我們需要做一下坐標修改或者將錨點設置到(0,0)的位置上。比如說:
anchorPoint = new CCPoint(0, 0);
下面簡單說一下代碼,cocos2dxna的坐標周是在屏幕的左下,這一點和cocos2d其他版本是一致的,主要是為了統一標准,當然這也帶來了理解上的麻煩,當然了,萬能的導演(CCDirector)也提供了轉換方法,但是我們在這里不需要太多,為了統一性,建議就按照左下的坐標開發比較好。
CCSprite的CCSprite.spriteWithFile靜態方法可以很方便的將我們所需圖片生成,不必自己在寫很多的代碼了,只需要一行,spriteWithFile所取得是對應在Content資源工程里的圖片文件,CCSprite也可以控制其坐標位置,開始場景中,就用了position來控制位置,將Logo固定到了中間偏上的位置。
按鈕類CCMenu單獨是沒有作用的,需要通過多個子項目來初始化自己,所以就有了兩個菜單的代碼,CCMenuItemImage也有靜態方法幫助開發者寫很少的代碼完成按鈕,CCMenuItemImage是CCMenuItem的派生類,由CCMenuItem派生的還有CCMenuItemLabel、CCMenuItemSprite等,它們的作用跟名字一樣,只是看如何方便使用了。
去掉FPS |
這個時候會說左下角的幀數顯示實在太難受了,能不能去掉,當然可以,直接把導演的DisplayFPS設置成為false就可以,但是cocos2dxna有個bug,去掉之后運行是下面這個樣子的:
這個bug的解決方法,也很簡單,就是在AppDelegate里初始化一下Font就行了,這是因為內部的處理機制造成的。
CCLabelTTF a = CCLabelTTF.labelWithString("0", "Arial", 0);
加入上面的代碼就可以,不用添加進去,現在運行看看:
是不是帥多了?也許現在迫不及待的趕緊弄下一個場景,先打住,現在聊聊更加重要的話題:
龐大的資源 紋理圖片優化 plist |
現在打開你的工程目錄找到bin下面所編譯的程序,看看Content里(Content是輸出工程的內容集合,你所見的都將會打包到XAP中)輸出的XNB文件吧:
現在,你能忍嗎?其實原圖不打包才400多KB,為什么轉換之后就變成這么誇張了呢,因為XNA對資源內容都會自行編譯輸出,這是為了方便自己,同時將不規格的資源內容編譯成規格的,這方面如果說多了就會涉及到圖像渲染的細節,這么說吧,對於圖像渲染顯示而言,它們其實只認2的N次冪長寬的圖像,無論是程序還是硬件,它的輸入和輸出都遵循這個規則,所以,你的精美小圖片不管用什么存儲最終都會變成統一規格。
一種方法是通過圖像紋理的模式修正,將其變成2的N次冪長寬的圖像,請看下圖:
你的所有的圖像都會默認為color格式,所以很悲催的事實就是將面臨超大的圖像素材體積(內部還給你擴展成了2的N次冪),DxtCompressed格式則可以大大的減小圖像體積,但是DxtCompressed對圖像有一定的要求,最基本的要求是:2的N次冪寬高
對於圖像資源,很難有正好的符合,刻意的制作就會代碼N多代碼的修正,我們利用cocos2d的特性來解決,在cocos2d有一種將很多圖片保存成為一張大圖片,然后獨取出來單獨使用,這個方法就是plist的圖片幀文件,它能極大的減小圖片體積,最重要的是大圖就能符合2的N次冪寬高的要求了。
TexturePackerGUI是專門制作cocos2d plist文件的軟件,這個軟件最好的優勢是有Windows版本的(有很多優秀的工具都在IOS運行),下面是簡單的使用方法:
先打開TexturePackerGUI,將前面的開始界面素材拖入到窗口中。
建議將DataFormat改成cocos2d-0.99.4,然后點擊Publish按鈕,保存為GameUI01.plist,瀏覽位置就會發現多出一個GameUI01.png,它們之間就是對應的,現在我們在程序里使用它們,將其添加到Content工程里,然后做如下兩個修改:
1、修改一下GameUI01.png的Content Processor內Textrue Format屬性為DxtCompressed。
2、修改GameUI01.plist的輸入和輸出管線,因為plist需要cocos2dxna的獨特的內容管線,所以先添加引用:
然后選擇GameUI.plist屬性,將輸入和輸出的管線修改:
現在編譯一下看看,呵呵,你會發現一個錯,這個錯是關於重復名稱的,所以你需要將生成的plist文件和png文件分開,比如說建立一個images目錄,推薦在plist所在的文件目錄下建立Images目錄將對應的png加入,因為在代碼中會自動處理並尋找對應的圖像文件,好了,現在再來一次編譯吧。
現在再看GameUI01所生成的兩個xna文件,兩個加起來只有1MB,已經大大的減少了體積,在png圖像里還有很多的空位,也許完全能夠留給其他的UI界面。
如何使用plist |
下一步就是如何在代碼中使用plist文件,打開SceneStart.cs代碼我們做一下改造。
public class SceneStart : CCScene { public SceneStart() { base.init(); CCSpriteFrameCache.sharedSpriteFrameCache().addSpriteFramesWithFile("GameUI01", "images/GameUI01"); //取得屏幕大小 CCSize size = CCDirector.sharedDirector().getWinSize(); //背景圖 CCSprite background = CCSprite.spriteWithSpriteFrameName("bg_start.png") ; background.anchorPoint = new CCPoint(0, 0); this.addChild(background); //Logo圖 CCSprite logo = CCSprite.spriteWithSpriteFrameName("logo.png"); //設置到界面中間偏上 logo.position = new CCPoint(size.width / 2, size.height / 2 + 120); this.addChild(logo); //兩個按鈕 CCMenuItemSprite btn_start = CCMenuItemSprite.itemFromNormalSprite( CCSprite.spriteWithSpriteFrameName("btn_start1.png"), CCSprite.spriteWithSpriteFrameName("btn_start2.png"), this, click_start); CCMenuItemSprite btn_setting = CCMenuItemSprite.itemFromNormalSprite( CCSprite.spriteWithSpriteFrameName("btn_setting1.png"), CCSprite.spriteWithSpriteFrameName("btn_setting2.png"), this, click_start); //MenuItem需要通過CCMenu組合 CCMenu menu = CCMenu.menuWithItems(btn_start, btn_setting); //一個垂直間隔排列 menu.alignItemsVerticallyWithPadding(10); //設置到界面中間偏下 menu.position = new CCPoint(size.width / 2, size.height / 2 - 120); this.addChild(menu); } private void click_start(CCObject sender) { } private void click_setting(CCObject sender) { } }
這段代碼中使用CCSpriteFrameCache載入了plist文件和png文件,用它們來提前所需要的圖片幀,之后在程序中使用,CCSpriteFrameCache是一個倉庫,使用文件名來標識所有的內容資源,CCSprite.spriteWithSpriteFrameName能夠直接依據文件名從中取出使用,關於CCSpriteFrameCache將應用在動畫等圖像處理方面,這次僅僅是一個簡單的圖片應用示例。
本次代碼仍然在:https://github.com/Nowpaper/SanguoCommander_cocos2dxna_Sample
關於TexturePackerGUI軟件,可以在網上搜索到使用。
本想在本次寫完切換的,看了看內容已經夠多了,還是下一篇完成吧:)