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);
//嘿嘿,偷懶沒自己打一遍程式。
資源的部分就完結了,還蠻複雜的,功能感覺也不太完善的樣子。這個部分和遊戲優化有直接關係,尤其是資源的釋放。在遊戲製作的後期應該很有用。目前,我覺得可以先放到一邊。