天天看點

《Cocos2D權威指南》——3.2 CCNode節點類

ccnode是cocos2d中最重要的類,同時也是所有節點的基類。它是一個抽象類,沒有視覺表現,定義了所有節點都通用的屬性和方法。

在cocos2d中,所有要繪制到螢幕的對象,或是自身包含要繪制到螢幕中的對象,都屬于ccnode類。最重要的幾個ccnode類分别是ccscene、cclayer、ccsprite、ccmenu,這也是我們本章要重點學習的内容。

ccnode的主要作用:

包含其他的ccnode節點(addchild、getchildbytag、removechild等方法);

通過定時器預定消息(schedule、unschedule等方法);

執行動作(runaction、stopaction等方法)。

注意 作為抽象類,ccnode是沒有自身紋理的。

3.2.1 ccnode類的屬性

ccnode類的常見屬性包括以下各種。

(1)anchorpoint

anchorpoint表示錨點。節點的變形和定位操作都要依據錨點來确定。錨點的變量類型是cgpoint。

錨點值通常在0~1之間,(0,0)代表左下角,而(1,1)代表右上角。預設ccnode節點錨點值是(0,0),也就是節點左下角。另外,還有anchorpointinpoints屬性,差別在于其采用絕對像素值為機關。

(2)camera

camera用于設定遊戲中的視角,利用opengl es中的glulookat()。變量類型是cccamera。

隻有在建立3d效果時才會用到camera屬性。如果使用了該屬性,就不能再同時使用rotation、scale、position這些屬性。

注意 cocos2d不推薦直接使用camera。如果需要實作一個視差滾動的背景(人物向前移動時,遊戲場景向身後移動,并且遠近不同的背景移動速度還不一樣,近的物體移動速度快,遠的物體移動速度慢,即所謂的視差),通過移動camera來實作會變得更複雜,而且會使cocos2d本身的一些功能特性遭受破壞。推薦的作法是使用ccparallaxnode,後面章節中我們會向大家示範如何做。

(3)children

children為節點的子節點數組。變量類型是ccarray。

ccarray是專門為了性能優化而設計的類,它的功能和nsmutablarray差不多。推薦在cocos2d中盡量使用ccarray替代nsmutablearray。

(4)contentsize

contentsize為未經轉換的節點大小,以points(點值)為機關。contentsize的變量類型是cgsize,預設值為(0,0)。

無論節點如何縮放或旋轉,contentsize屬性值始終不變。所有的節點都有大小,而layer(層)和screen(場景)大小就是螢幕大小。

contentsize主要用于碰撞檢測,我們可以根據節點目前所在位置以及節點紋理本身的大小來計算碰撞矩形區域,具體代碼如代碼清單3-2所示。

代碼清單3-2 計算碰撞矩形區域

(5)glserverstate

glserverstate表示opengles伺服器端狀态,從cocos2d v2.0版本開始使用。變量類型是ccglserverstate,可參考ccglstate.h。

(6)grid

在對節點應用某些特殊效果時會用到此屬性。變量類型是ccgridbase。

(7)isrelativeanchorpoint

該屬性為yes時,節點的變形将基于錨點進行。變量類型是bool。

對于精靈、标簽和其他可調整大小的節點會預設啟用該屬性;而對于場景、層和其他“全屏”對象,會預設禁用該屬性。

(8)isrunning

isrunning用于判斷目前節點是否在運作。變量類型是bool。

(9)orderofarrival

當使用同樣的z值對子節點進行排序的時候,用該屬性來決定子節點的順序,不要手動更改該數值。變量類型是nsuinteger。

(10)parent

parent表示對節點父節點的弱引用,通常很少用到。變量類型是ccnode。

(11)position

position表示節點在螢幕中的位置。變量類型是cgpoint,以points(點值)為機關,螢幕的左下角坐标是(0,0)。

此外,positioninpixels屬性同樣表示節點在螢幕中的位置,不過機關為pixels(像素值),變量類型是cgpoint,預設值為(0,0)。

(12)rotation

rotation表示節點沿順時針方向旋轉的角度。變量類型是float,預設值為0。

(13)scale

scale表示節點的縮放比例。變量類型是float,有三個屬性,預設值為(scalex=1,scaley=1)。

scale:節點沿x和y坐标軸的整體縮放比例。

scalex:節點沿x軸的縮放比例。

scaley:節點沿y軸的縮放比例。

(14)shaderprogram

shaderprogram表示着色程式。變量類型是glprogram。

該屬性從cocos2d v2.0版本開始使用,詳細資訊可參考glprogram.h。後面會專門用一章介紹如何為ccnode編寫定制的shader程式。

(15)skew

skew表示節點的變形角度。變量類型是float。

skewx:沿x軸方向順時針切向畸變角度(y軸和節點形狀左邊緣之間的角度),預設值為0。

skewy:沿y軸方向逆時針切向畸變角度(x軸和節點形狀底邊的角度),預設值為0。

(16)tag

tag用于識别節點的辨別值。變量類型是nsinteger。

無論是建立、引用還是删除節點,tag值都有用武之地。比如,tag參數允許通過getchildbytag方法擷取指定節點。如果有多個節點擁有相同tag數值,getchildbytag會将找到的第一個節點傳回,将不再通路其他節點,是以要確定為節點指定獨有的tag數值。

tag在很多應用場景以及cocos2d遊戲程式設計過程中都起到重要作用。最簡單的應用就是在其他scheduler的selector函數裡通過getchildbytag得到對應tag節點,這樣無需在類的定義裡聲明過多的節點弱引用(weak ref)。此外,tag還有一個重要的應用場景。多個ccmenuitem共用一個selector時,可以給menuitem賦予不同tag,然後在selector裡根據tag值判斷玩家具體觸碰的是哪一個按鈕。

(17)userdata

userdata為使用者自定義的資料指針對象。變量類型是void。

userdata經常用于selector之間的資料傳遞,或者其他需要節點攜帶傳遞資料的場合。

(18)visible

visible用于判斷節點是否可見。變量類型是bool,預設值為yes。

(19)zorder

zorder表示節點相對于其“兄弟”節點(擁有共同的父節點)z順序值。變量類型是nsinteger。

對于像ccsprite這樣有視覺呈現的節點,該參數決定了節點的繪制順序,擁有最小z值的節點會首先被繪制,擁有最大z值的節點最後被繪制。如果多個節點擁有相同z值,繪制順序将由它們的添加順序來決定。

(20)vertexz

vertexz表示真正的opengl z頂點。opengl z頂點和cocos2d z順序的差別如下:

opengl z修改z頂點,而非父節點和子節點間的z順序;

opengl z可能需要設定2d投影;

如果所有節點使用相同的opengl z頂點,cocos2d z順序仍然保持正常。

使用該值可能會破壞cocos2d中的父節點–子節點z順序,是以通常較少使用。

以上隻是對ccnode類屬性的簡單介紹,要真正了解每個屬性在開發cocos2d遊戲中的作用,需要在實際開發中逐漸體會。在開發過程中大家可以随時回顧本章查找相關屬性。第2章的示例代碼運用了一部分ccnode屬性,大家可以多多學習并修改代碼,體會這些屬性的用途。

3.2.2 ccnode類的方法

ccnode類中所實作的方法可以分為三個大類,分别是對子節點的處理、使用定時器預定消息,以及執行動作。此外有些方法不屬于以上三大類,下面将一一介紹。

1 . 處理子節點

ccnode類實作了所有添加、擷取和删除子節點的方法。以下是一些處理子節點的方法:

1)建立一個新的節點。示例代碼如下:

請注意,這行代碼等同于:

2)将新節點添加為目前節點的子節點,并設定子節點的z值和tag值。

如果将該子節點添加到“運作”模式,則立即調用“onenter”和“onentertransitiondidfinish”方法。示例代碼如下:

3)使用節點的辨別擷取子節點。示例代碼如下:

4)通過tag删除子節點。

如果cleanup的參數值為yes,則停止任何運作中的動作。示例代碼如下:

5)通過節點指針删除子節點。

6)删除一個節點的所有子節點。

7)從目前節點的父節點删除目前節點。

如果cleanup的參數值為yes,将删除所有的動作和回調方法;如果目前節點沒有父節點,則不執行任何操作。示例代碼如下:

2 . 執行動作

ccnode可以使用動作(actions)讓節點執行某些動作。本書第4章将專門講述動作的詳細内容,現在我們隻需要知道使用動作可以讓節點移動、旋轉和縮放,以及做一些其他事情。

1)運作某個特定的動作。示例代碼如下:

其中action是使用ccaction定義的某個動作。

2)停止所有在該節點上運作的動作。示例代碼如下:

3)停止在該節點上運作的某個特定動作。示例代碼如下:

4)停止運作的動作清單中的某個特定動作,使用tag辨別來區分。示例代碼如下:

5)擷取目前運作的動作清單中的某個特定動作,使用tag辨別來區分。示例代碼如下:

如果想在以後使用此動作,可以使用這個方法。

6)擷取運作動作的數量。

包括正在運作的動作,還包括預定運作的動作(在actionstoadd和動作數組中的動作),複合動作算一個動作。示例代碼如下:

3 . 預定消息

ccnode節點可以預定消息,其實就是每隔一段時間調用一次方法。在很多遊戲中需要節點調用特定的更新方法來處理某些情況,比如碰撞測試等。

1)每幀都調用的更新方法,每個節點隻可預定一個update方法。示例代碼如下:

其中,delta參數表示該方法的上一次調用到目前所經過的遊戲時間。

2)仍然是每幀都會調用的更新方法,每個節點隻可預定一個update方法,與1)的差別在于使用該方法可以安排更新方法的優先次序。更新方法的調用是按照優先級數值從小到大的次序。示例代碼如下:

所有節點(節點1、2、3)都會調用-(void)update: (cctime) delta方法。但因為使用了優先級設定,将會首先運作節點3的更新方法;然後是調用節點1的更新方法,因為節點1預設優先級設定為0;節點2的更新方法最後調用,因為它的優先級數值最大。

如果每幀都調用相同的更新方法,上述做法很适用。不過有時需要用到更靈活的更新方法。

3)指定運作特定的更新方法,并設定調用的時間間隔。示例代碼如下:

如果需要每一幀都觸發某個方法,應該使用scheduleupdate方法,并把要定時處理的邏輯放到update方法中。但是update方法隻有一個,是以,大部分情況下大家會使用上述代碼來觸發不同的定時更新邏輯。

4)指定運作特定的更新方法,并設定調用的延遲時間,但隻運作一次。示例代碼如下:

5)停止節點的某個指定選擇器,但該方法不會停止scheduleupdate中設定的預定更新方法。想要停止scheduleupdate中設定的預定更新方法,可以使用unscheduleupdate方法。示例代碼如下:

6)停止節點的所有選擇器(selector),包括在scheduleupdate裡設定的update選擇器,該方法不會影響節點的動作(action)。示例代碼如下:

7)用_cmd關鍵詞停止目前方法的預定。示例代碼如下:

4 . 其他方法

(1)-(cgrect)boundingbox

該方法用于擷取節點的邊框,傳回的坐标是相對于其父節點的。以points(點值)為機關,傳回cgrect變量類型的值。

boundingbox在進行遊戲物體碰撞檢測時非常有用,功能類似之前定義的rectofsprite方法。比如,可以把第2章示例遊戲中的碰撞檢測部分更新為代碼清單3-3。

代碼清單3-3 碰撞檢測代碼更新

(2)-(void)cleanup

該方法用于停止所有運作中的動作和預定方法。

(3)-(cgpoint)converttonodespace:(cgpoint)worldpoint

該方法用于将點坐标轉換成節點空間坐标。以points(點值)為機關,傳回cgpoint變量類型的值。

(4)-(cgpoint)converttonodespacear:(cgpoint)worldpoint

該方法用于将點坐标轉換成相對于錨點的節點空間坐标。以points(點值)為機關,傳回cgpoint變量類型的值。

(5)-(cgpoint)converttoworldspace:(cgpoint)nodepoint

該方法用于将節點空間坐标轉換成世界空間坐标。以points(點值)為機關,傳回cgpoint變量類型的值。

(6)-(cgpoint)converttoworldspace:(cgpoint)nodepoint

該方法用于将節點空間坐标轉換成相對于錨點的世界空間坐标。以points(點值)為機關,傳回cgpoint變量類型的值。

注意,第2章的示例遊戲中,假如發射子彈的需求有所改變,比如隻有玩家“點中”飛機才開始發射子彈,實作方式如代碼清單3-4所示。

代碼清單3-4 發射子彈實作

大家可以找到本章示例代碼,根據代碼注釋體驗4種檢測玩家的觸摸點是否在playersprite區域内的方法,相信會對局部坐标和世界坐标有一定的了解,同時明白boundingbox是相對于節點所處的世界坐标來計算的。通過幾個小實驗,應該已經掌握boundingbox和texturerect的功能與差別。

(7)-(void)draw

覆寫該方法以繪制自己的節點。在xcode中打開helloworldlayer.m,實作draw方法,如代碼清單3-5所示。

代碼清單3-5 draw方法實作

此時編譯運作,我們并不能看到這條從(10,10)到(200,200)、紅色、寬度為8像素的線。因為程式中添加了背景精靈圖檔,是以需要把之前添加背景圖檔的代碼注釋掉:

編譯并運作代碼,将會得到如圖3-3所示畫面。

仔細觀察的話大家會發現,在helloworldlayer裡添加的任何節點,在經過這條紅線時都會将紅線上的點覆寫。因為cocos2d的繪制是先調用節點自身的draw,然後再調用它所有子節點的draw方法。

《Cocos2D權威指南》——3.2 CCNode節點類

(8)-(id)init

該方法用于初始化節點。

有一點需要注意,我們應該盡量把遊戲場景中用到的sprite、label、menu、action、animation等對象在init方法中建立好。如果不想讓玩家在進入場景時就看到,可以把些節點的visible屬性先設定為no;在後面需要使用這些預配置設定的對象時,就可以直接把visbile設定為yes,這樣做能提高遊戲性能。這種預先配置設定對象的政策,也叫做lazy loading。第2章示例中的玩家sprite和敵機sprite,以及子彈sprite都采用了這種方式,這種做法有助于提高遊戲性能。

(9)- (cgaffinetransform) nodetoparenttransform

該方法傳回一個矩陣,可以将節點(本地)空間坐标轉換為父節點的空間坐标,該矩陣以像素值為機關。

(10)- (cgaffinetransform) nodetoworldtransform

該方法傳回一個世界坐标的仿射轉換矩陣,該矩陣以像素值為機關。

(11)-(void)onenter

該方法為回調方法,當ccnode節點進入“舞台”時調用。如果進入時帶有過渡效果,則在過渡開始時調用。

(12)-(void)onentertransitiondidfinish

該方法為回調方法,當ccnode節點進入舞台時調用。如果帶有過渡效果,則在過渡完成時調用。

(13)-(void)onexit

該方法為回調方法,當ccnode節點離開舞台時會被調用。如果帶有過渡效果,則在過渡完成時調用。

(14)- (void) parenttonodetransform

該方法傳回一個矩陣,可以将父節點的空間坐标轉換為節點(本地)空間坐标,該矩陣以像素值為機關。

(15)- (void) pauseschedulerandactions

該方法暫停所有預定的選擇器方法和動作,由onexit方法在其内部調用。

(16)- (void) reorderchild: (ccnode *) childz:(nsinteger) zorder

該方法重新設定子節點的次序,該子節點必須已經添加。

(17)- (void) resumeschedulerandactions

該方法繼續所有預定的選擇器方法和動作。該方法由onenter方法在其内部調用。

(18)- (void) sortallchildren

使用該方法可以改善遊戲性能。該方法在每次繪制前對子節點數組進行排序,除非某個添加的子節點需要在同一幀被清除,不要手動調用該方法。

(19)- (void) transform

該方法根據節點的位置、比例、旋轉和其他屬性來執行opengles視圖–矩陣轉換。

(20)- (void) transformancestors

該方法從其祖先節點執行opengles視圖–矩陣轉換。

(21)-(void)visit

該方法為遞歸方法,通路節點的子節點并繪制它們。

(22)- (cgaffinetransform) worldtonodetransform

該方法傳回逆向的世界坐标仿射轉換矩陣,以像素值為機關。

以上就是ccnode類的主要方法,詳細定義可以檢視cocos2d模闆中的ccnode.h檔案。

繼續閱讀