(三)訪問節(jié)點(diǎn)和組件

(三)訪問節(jié)點(diǎn)和組件

你可以在 屬性檢查器 里修改節(jié)點(diǎn)和組件,也能在腳本中動(dòng)態(tài)修改。動(dòng)態(tài)修改的好處是能夠在一段時(shí)間內(nèi)連續(xù)地修改屬性、過渡屬性,實(shí)現(xiàn)漸變效果。腳本還能夠響應(yīng)玩家輸入,能夠修改、創(chuàng)建和銷毀節(jié)點(diǎn)或組件,實(shí)現(xiàn)各種各樣的游戲邏輯。要實(shí)現(xiàn)這些效果,你需要先在腳本中獲得你要修改的節(jié)點(diǎn)或組件。
在本篇教程,我們將介紹如何

  • 獲得組件所在的節(jié)點(diǎn)
  • 獲得其它組件
  • 使用 屬性檢查器 設(shè)置節(jié)點(diǎn)和組件
  • 查找子節(jié)點(diǎn)
  • 全局節(jié)點(diǎn)查找
  • 訪問已有變量里的值

獲得組件所在的節(jié)點(diǎn)

獲得組件所在的節(jié)點(diǎn)很簡(jiǎn)單,只要在組件方法里訪問 this.node 變量:

    start: function () {
        var node = this.node;
        node.x = 100;
    }

獲得其它組件

你會(huì)經(jīng)常需要獲得同一個(gè)節(jié)點(diǎn)上的其它組件,這就要用到 getComponent 這個(gè) API,它會(huì)幫你查找你要的組件

    start: function () {
        var label = this.getComponent(cc.Label);
        var text = this.name + ' started';

        // Change the text in Label Component
        label.string = text;
    }

你也可以為 getComponent 傳入一個(gè)類名。對(duì)用戶定義的組件而言,類名就是腳本的文件名,并且區(qū)分大小寫。例如 "SinRotate.js" 里聲明的組件,類名就是 "SinRotate"。

var label = this.getComponent("cc.Label");

在節(jié)點(diǎn)上也有一個(gè) getComponent 方法,它們的作用是一樣的:

    start: function () {
        cc.log( this.node.getComponent(cc.Label) === this.getComponent(cc.Label) );  // true
    }

如果在節(jié)點(diǎn)上找不到你要的組件,getComponent 將返回 null,如果你嘗試訪問 null 的值,將會(huì)在運(yùn)行時(shí)拋出 "TypeError" 這個(gè)錯(cuò)誤。因此如果你不確定組件是否存在,請(qǐng)記得判斷一下:

    start: function () {
        var label = this.getComponent(cc.Label);
        if (label) {
            label.string = "Hello";
        }
        else {
            cc.error("Something wrong?");
        }
    }

獲得其它節(jié)點(diǎn)及其組件

僅僅能訪問節(jié)點(diǎn)自己的組件通常是不夠的,腳本通常還需要進(jìn)行多個(gè)節(jié)點(diǎn)之間的交互。例如,一門自動(dòng)瞄準(zhǔn)玩家的大炮,就需要不斷獲取玩家的最新位置。Cocos Creator 提供了一些不同的方法來獲得其它節(jié)點(diǎn)或組件。

使用 屬性檢查器 設(shè)置節(jié)點(diǎn)和組件

最直接的方式就是在 屬性檢查器 中設(shè)置你需要的對(duì)象。以節(jié)點(diǎn)為例,這只需要在腳本中聲明一個(gè) type 為 cc.Node 的屬性:

// Cannon.js

cc.Class({
    extends: cc.Component,
    properties: {
        // 聲明 player 屬性
        player: {
            default: null,
            type: cc.Node
        }
    }
});

這段代碼在 properties 里面聲明了一個(gè) player 屬性,默認(rèn)值為 null,并且指定它的對(duì)象類型為 cc.Node。這就相當(dāng)于在其它語言里聲明了 public cc.Node player = null;。腳本編譯之后,這個(gè)組件在 屬性檢查器 中看起來是這樣的:


此處輸入圖片的描述
此處輸入圖片的描述

接著你就可以將層級(jí)管理器上的任意一個(gè)節(jié)點(diǎn)拖到這個(gè) Player 控件:


此處輸入圖片的描述
此處輸入圖片的描述

這樣一來它的 player 屬性就會(huì)被設(shè)置成功,你可以直接在腳本里訪問 player:
// Cannon.js

var Player = require("Player");

cc.Class({
    extends: cc.Component,
    properties: {
        // 聲明 player 屬性
        player: {
            default: null,
            type: cc.Node
        }
    },

    start: function () {
        var playerComp = this.player.getComponent(Player);
        this.checkPlayer(playerComp);
    },

    // ...
});

利用屬性檢查器設(shè)置組件

在上面的例子中,如果你將屬性的 type 聲明為 Player 組件,當(dāng)你拖動(dòng)節(jié)點(diǎn) "Player Node" 到 屬性檢查器,player 屬性就會(huì)被設(shè)置為這個(gè)節(jié)點(diǎn)里面的 Player 組件。這樣你就不需要再自己調(diào)用 getComponent 啦。

// Cannon.js

var Player = require("Player");

cc.Class({
    extends: cc.Component,
    properties: {
        // 聲明 player 屬性,這次直接是組件類型
        player: {
            default: null,
            type: Player
        }
    },

    start: function () {
        var playerComp = this.player;
        this.checkPlayer(playerComp);
    },

    // ...
});

你還可以將屬性的默認(rèn)值由 null 改為數(shù)組[],這樣你就能在 屬性檢查器 中同時(shí)設(shè)置多個(gè)對(duì)象。
不過如果需要在運(yùn)行時(shí)動(dòng)態(tài)獲取其它對(duì)象,還需要用到下面介紹的查找方法。

查找子節(jié)點(diǎn)

有時(shí)候,游戲場(chǎng)景中會(huì)有很多個(gè)相同類型的對(duì)象,像是炮塔、敵人和特效,它們通常都有一個(gè)全局的腳本來統(tǒng)一管理。如果用 屬性檢查器 來一個(gè)一個(gè)將它們關(guān)聯(lián)到這個(gè)腳本上,那工作就會(huì)很繁瑣。為了更好地統(tǒng)一管理這些對(duì)象,我們可以把它們放到一個(gè)統(tǒng)一的父物體下,然后通過父物體來獲得所有的子物體:

// CannonManager.js

cc.Class({
    extends: cc.Component,

    start: function () {
        this.cannons = [];
        this.cannons = this.node.getChildren();
    }
});

這里的 getChildren 是 cc.Node 原有的一個(gè) API,可以獲得一個(gè)包含所有子節(jié)點(diǎn)的數(shù)組。

你還可以使用 getChildByName:

this.node.getChildByName("Cannon 01");

如果子節(jié)點(diǎn)的層次較深,你還可以使用 cc.find,cc.find 將根據(jù)傳入的路徑進(jìn)行逐級(jí)查找:

cc.find("Cannon 01/Barrel/SFX", this.node);

全局節(jié)點(diǎn)查找

當(dāng) cc.find 只傳入第一個(gè)參數(shù)時(shí),將從場(chǎng)景根節(jié)點(diǎn)開始逐級(jí)查找:

this.backNode = cc.find("Canvas/Menu/Back");

訪問已有變量里的值

如果你已經(jīng)在一個(gè)地方保存了節(jié)點(diǎn)或組件的引用,你也可以直接訪問它們,一般有兩種方式:

  • 通過全局變量訪問
    你應(yīng)當(dāng)很謹(jǐn)慎地使用全局變量,當(dāng)你要用全局變量時(shí),應(yīng)該很清楚自己在做什么,我們并不推薦濫用全局變量,即使要用也最好保證全局變量只讀。
    讓我們?cè)囍x一個(gè)全局對(duì)象 window.Global,這個(gè)對(duì)象里面包含了 backNode 和 backLabel 兩個(gè)屬性。
// Globals.js, this file can have any name

window.Global = {
    backNode: null,
    backLabel: null,
};

由于所有腳本都強(qiáng)制聲明為 "use strict",因此定義全局變量時(shí)的 window. 不可省略。
接著你可以在合適的地方直接訪問并初始化 Global:

// Back.js

cc.Class({
    extends: cc.Component,

    onLoad: function () {
        Global.backNode = this.node;
        Global.backLabel = this.getComponent(cc.Label);
    }
});

初始化后,你就能在任何地方訪問到 Global 里的值:

// AnyScript.js

cc.Class({
    extends: cc.Component,

    // start 會(huì)在 onLoad 之后執(zhí)行,所以這時(shí) Global 已經(jīng)初始化過了
    start: function () {
        var text = 'Back';
        Global.backLabel.string = text;
    }
});
訪問全局變量時(shí),如果變量未定義將會(huì)拋出異常。
添加全局變量時(shí),請(qǐng)小心不要和系統(tǒng)已有的全局變量重名。
你需要小心確保全局變量使用之前都已初始化和賦值。
  • 通過模塊訪問
    如果你不想用全局變量,你可以使用 require 來實(shí)現(xiàn)腳本的跨文件操作,讓我們看個(gè)示例:
// Global.js, now the filename matters

module.exports = {
    backNode: null,
    backLabel: null,
};

每個(gè)腳本都能用 require + 文件名(不含路徑) 來獲取到對(duì)方 export 的對(duì)象

// Back.js

// this feels more safe since you know where the object comes from
var Global = require("Global");

cc.Class({
    extends: cc.Component,

    onLoad: function () {
        Global.backNode = this.node;
        Global.backLabel = this.getComponent(cc.Label);
    }
});
// AnyScript.js

// this feels more safe since you know where the object comes from
var Global = require("Global");

cc.Class({
    extends: cc.Component,

    // start 會(huì)在 onLoad 之后執(zhí)行,所以這時(shí) Global 已經(jīng)初始化過了
    start: function () {
        var text = "Back";
        Global.backLabel.string = text;
    }
});
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,835評(píng)論 6 534
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,676評(píng)論 3 419
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,730評(píng)論 0 380
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,118評(píng)論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,873評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,266評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,330評(píng)論 3 443
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,482評(píng)論 0 289
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,036評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,846評(píng)論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,025評(píng)論 1 371
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,575評(píng)論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,279評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,684評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,953評(píng)論 1 289
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,751評(píng)論 3 394
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,016評(píng)論 2 375

推薦閱讀更多精彩內(nèi)容

  • 1.除了方法, 其他東西都要扔到properties里面了, 并且要給出屬性的默認(rèn)值或者屬性的存取的方法 1) 首...
    視掘閱讀 1,349評(píng)論 0 0
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,789評(píng)論 18 139
  • 開發(fā)工具cocos creator。 比較隨意,看demo源碼總結(jié) 1.平臺(tái): 當(dāng)前平臺(tái)系統(tǒng):cc.sys.os ...
    紫荊逸閱讀 2,557評(píng)論 0 1
  • 接觸Cocos-JS開發(fā)10多天以來,漸漸熟悉了Cocos的一些東西,當(dāng)然也遇到了一些埂,官方的文檔還是挺詳細(xì)的,...
    不做需要減肥的人閱讀 1,117評(píng)論 0 3
  • 每當(dāng)聽到一首旋律好聽的歌曲。 每當(dāng)觀看一部吸引人的電視劇、電影。 每當(dāng)用幾天幾夜看一本網(wǎng)絡(luò)爽文。 每當(dāng)玩一款精美的...
    玩吉閱讀 288評(píng)論 0 0