1. 程式人生 > >cocos creator 學習筆記(四)——節點與資源篇

cocos creator 學習筆記(四)——節點與資源篇

回顧一下,我們在前面學習了指令碼檔案中不同的回撥函式對應的功能。如何訪問自身和其它節點與元件,以及常用的節點元件的介面功能。接下來開始第四篇的學習。

1、建立新節點——new cc.Node()

start : function ( ) {
  var node = new cc.Node('Sprite');        //new cc.Node() 方法建立了定義為node的新節點
  var sp = node.addComponent(cc.Sprite);    //為新節點node加入Sprite元件命名為sp

  sp.spriteFrame = this.sprite;            //初始化sp元件
  node.parent = this.node;                //為新節點設定父節點
},

2、克隆已有節點——cc.instantiate

start : function (){
  var scene = cc.director.getScene();       //得到一個場景變數,cc.director提供的API
  var node = cc.instantiate(this.target);    //克隆一個和this.target節點相同的節點

  node.parent = scene;                       //設定新節點的父節點
  node.setPosition(0,0);                       //設定新節點的位置
},

3、建立預製節點和克隆節點的方法完全相同——cc.instantiate

只是this.target指向的目標型別不同——一個是cc.Node ; 另外一個是 cc.Prefab。

4、銷燬節點——node.destory()

start : function () {
  setTimeout(function(){                    //設定了一個setTimeout函式,用來延時。第一個引數是執行功能,第二個引數是時間,5000毫秒
                this.target.destory();
                       }.bind(this),5000);    //這裡對this.target進行銷燬,之後這個bind(this)百度一下是繫結this指標的朝向;因為我們之後還會對這個物件檢測是否銷燬成功,所以這裡綁定了一下。
},
update : function(dt){
  if(cc.isValid(this.target)){                //cc.isValid()判斷指向節點是否被銷燬。
    this.target.rotation += dt * 10.0;        //未被銷燬則節點每幀轉10度(+= dt * 10.0)
  }
},

4、我們的遊戲不可能只有一個場景,所以接下來學習載入和切換場景。

載入場景:

cc.director.loadScene("MyScene");    //cc.director.loadScene 引數為場景名""記得雙引號,不含字尾

常駐節點:場景的切換會摧毀所有節點和例項——常駐節點可以在轉場操作中保持不變

cc.game.addPersistRootNode(myNode);    //設定節點為常駐

cc.game.removePersistRootNode(myNode);    //取消節點常駐屬性

場景載入回撥:

cc.director.loadScene("MyScene", onSceneLaunched);   

//這裡給loadScene添加了第二個引數,這個引數就是宣告在本指令碼中的一個回撥函式,專門用來在載入場景後完成組發的初始化和資料傳遞操作。——為了保證回撥函式不會被摧毀,所以通常會繫結到常駐節點上。

預載入場景

我們可以提前在後臺靜默載入新場景,並手動按鈕切換以保持流暢性。

cc.director.preloadScene("table",function(){        //這裡呼叫了preloadScene方法
  cc.log("Next Scene preloaded");                    //引數功能為在預載入時顯示一個文字框訊息
});

注意——我們仍然需要使用 .loadScene 來真正切換場景。

5、資源——場景中用到的各色元件和內容

Asset類資源——自動統一載入的資源型別,cc.SpriteFrame , cc.AnimationClip , cc.Prefab 。沒什麼特別的,像原來那樣定義就好。

Raw Asset 資源——這類資源使用url字串來表示資源,cc.Texture2D \ cc.AudioClip \ cc.ParticleAsset ,這些資源在宣告定義時有特殊要求。

 textureURL: {
            default: "",
            url: cc.Texture2D        //注意,這裡資源型別不以'type'開頭,而是改為'url'
        }

6、動態載入資源——屬性檢查器裡設定資源是固定而無法更改的

我們在曾經的(二)中學習過——在指令碼中動態更改訪問節點。回顧一下,當時是使用一個父檔案包含大量子節點,通過關聯父檔案來呼叫子節點。

這裡我們要動態載入資源,原理相同——在資源管理器的assets目錄下手工建立resources資料夾。把需要使用指令碼直接動態載入的資源放在這個資料夾裡。至於這裡的——直接動態載入——我還不太瞭解具體是個什麼情況——繼續往下看看。

動態載入有一個專用的API(專門用來載入resources下的Asset)——cc.loader.loadRes
看看用法———好好用註釋分析一下

//動態載入一個資源
cc.loader.loadRes("test assets/prefab" , function (err,prefab){        //第一個引數是相對於resources的路徑。第二個引數是個功能函式。
  var newNode = cc.instantiate(prefab);            //新建一個節點,新增資源prefab
  cc.director.getScene().addChild(newNode);        //把新建節點設定為Scene的子節點
});
//載入AnimationClip
var self = this;                                   //儲存了this的指向,
cc.loader.loadRes("test assets/anim",function(err,clip){
  self.node.getComponent(cc.Animation).addClip(clip,"anim");    //呼叫self節點上的cc.Animation元件,並加入anim資源。addClip
});

//載入SpriteAtlas,並獲取其中一個SpriteFrame
cc.loader.loadRes("test assets/sheep",cc.SpriteAtlas, function(err,atlas){    \\這裡加入了一個引數——指定資源型別,使用cc.SpriteAtlas圖集資源時注意
  var frame = atlas.getSpriteFrame('sheep_down_0');        \\新建物件atlas.getSpriteFrame()得到圖集中的某張圖
sprite.spriteFrame = frame;
});

資源釋放——loadRes載入的資源可以通過releaseRes釋放。

cc.loader.releaseRes("test assets/image", cc.SpriteFrame);    //releaseRes 兩個引數一個是路徑,一個是型別。
cc.loader.releaseAsset(spriteFrame);                          //releaseAsset釋放特定的Asset例項。

7、動態載入Raw Asset 資源。注意,兩種資源之間的區別。

使用cc.loader.load 可以通過使用url從遠端載入。

如果是專案內的資源,動態載入方式同樣使用loadRes,與Asset資源相同

Raw Asset資源載入後,如果需要傳給url形式的API(這裡應該是需要用到一些web端或伺服器端的API)。需要進行url轉換提供完整路徑

var texture = c.textureCache.addImage("resources/test asset/image.png");    //這裡會對url報錯
var realUrl = cc.url.raw("resources/test assets/image.png");    //專門用cc.url.raw轉換一下url,應該是和API的url區分開
var texture = cc.textureCache.addImage(realUrl);

8、資源批量載入

cc.loader.loadResDir 載入相同路徑下的所有資源:——————省略操作?

cc.loader.loadResDir("test assets",function(err,assets){^});    //載入了test assets資料夾中的所有資源

cc.loader.loadResDir("test assets/sheep",cc.SpriteFrame,function(err,assets){^});//注意,這裡載入了sheep圖集中的所有cc.SpriteFrame元素。

9、載入遠端資源和裝置資源

載入遠端貼圖資源——————使用者自定義頭像等伺服器資源(這例子舉得好啊)。上面介紹的loadRes等API主要用於包內資源和本地資源。cc.loader.load是用來載入遠端資源的API。上面也提到了。

//第一種情況,網頁路徑與字尾名
var remoteUrl = "http://unknown.org/someres.png";
cc.loader.load(remoteUrl, function (err, texture) {    //cc.loader.load API 第一個引數是路徑,之後是功能函式
});

//第二種情況,網頁路徑無後綴
remoteUrl = "http://unknown.org/emoji?id=124982374";
cc.loader.load({url: remoteUrl, type: 'png'}, function () {      //注意,這裡不新增第二引數,而是擴充套件第一引數。{url: ,type:''}
    // Use texture to create sprite frame
});

//第三種情況,這裡有儲存裝置的絕對地址
var absolutePath = "/dara/data/some/path/to/image.png"    
cc.loader.load(absolutePath, function () {                    //注意,這是非包內的本地資源。使用方式與URL類似
    // Use texture to create sprite frame
});

10、資源的聯絡與釋放

由於資源是相互關聯的,預製prefab資源內會包含許多的SpriteFrame資源或Node資源。僅僅釋放Prefab並不會使這些關聯的底層資源一起被釋放。——注意,loader載入過的資源都會佔據記憶體,會影響不同計算機的執行速率。

所以我們必須自己判斷資源的釋放時機,以保證執行速度(明顯是小遊戲的思路,大型遊戲自己判斷資源釋放是會死人的我感覺)。看看一些簡單的資源釋放的示例,會有一些API。

// 直接釋放某個貼圖
cc.loader.release(texture);
// 釋放一個 prefab 以及所有它依賴的資源
var deps = cc.loader.getDependsRecursively('prefabs/sample'); //cc.loader.getDependsRecursively獲得所有依賴資源的API。
cc.loader.release(deps);
// 如果在這個 prefab 中有一些和場景其他部分共享的資源,你不希望它們被釋放,有兩種方法:
// 1. 顯式宣告禁止某個資源的自動釋放
cc.loader.setAutoRelease(texture2d, false);   //直接setAutoRealease(,false)直接說自動釋放 false。
// 2. 將這個資源從依賴列表中刪除
var deps = cc.loader.getDependsRecursively('prefabs/sample');    //這個方法複雜一些,目前不知道有什麼用
var index = deps.indexOf(texture2d._uuid); 
if (index !== -1)               
deps.splice(index, 1);
cc.loader.release(deps);
//嘿嘿,偷懶沒自己打一遍程式。

資源的部分就完結了,還蠻複雜的,功能感覺也不太完善的樣子。這個部分和遊戲優化有直接關係,尤其是資源的釋放。在遊戲製作的後期應該很有用。目前,我覺得可以先放到一邊。