(二)坐標系和節點變換屬性
標簽(空格分隔): 內容創作工作流程
在 場景編輯器 和 節點和組件 文檔中,我們介紹了可以通過 變換工具 和編輯 屬性檢查器 中節點的屬性來變更節點的顯示行為。這一節我們將會深入了解節點所在場景空間的坐標系,以及節點位置(Position)、旋轉(Rotation)、縮放(Scale)、尺寸(Size)四大變換屬性的工作原理。
Cocos Creator 坐標系
我們已經知道可以為節點設置位置屬性,那么一個有著特定位置屬性的節點在游戲運行時將會呈現在屏幕上的什么位置呢?就好像日常生活的地圖上有了經度和緯度才能進行衛星定位,我們也要先了解 Cocos Creator 的坐標系,才能理解節點位置的意義。
笛卡爾坐標系
Cocos Creator 的坐標系和 cocos2d-x 引擎坐標系完全一致,而 cocos2d-x 和 OpenGL 坐標系相同,都是起源于笛卡爾坐標系。笛卡爾坐標系中定義右手系原點在左下角,x 向右,y 向上,z 向外,我們使用的坐標系就是笛卡爾右手系。

屏幕坐標系和 cocos2d-x 坐標系
標準屏幕坐標系使用和 OpenGL 不同的坐標系,和 cocos2d-x 坐標系有很大區別。
在 iOS, Android, Windows Phone 等平臺用原生 SDK 開發應用時使用的是標準屏幕坐標系,原點為屏幕左上角,x 向右,y 向下。
Cocos2d-x 坐標系和 OpenGL 坐標系一樣,原點為屏幕左下角,x 向右,y 向上。

世界坐標系(World Coordinate)和本地坐標系(Local Coordinate)
世界坐標系也叫做絕對坐標系,在 Cocos Creator 游戲開發中表示場景空間內的統一坐標體系,「世界」就用來表示我們的游戲場景。
本地坐標系也叫相對坐標系,是和節點相關聯的坐標系。每個節點都有獨立的坐標系,當節點移動或改變方向時,和該節點關聯的坐標系將隨之移動或改變方向。
Cocos Creator 中的 節點(Node) 之間可以有父子關系的層級結構,我們修改節點的 位置(Position) 屬性設定的節點位置是該節點相對于父節點的 本地坐標系 而非世界坐標系。最后在繪制整個場景時 Cocos Creator 會把這些節點的本地坐標映射成世界坐標系坐標。
要確定每個節點坐標系的作用方式,我們還需要了解 錨點 的概念
錨點(Anchor)
錨點(Anchor) 是節點的另一個重要屬性,它決定了節點以自身約束框中的哪一個點作為整個節點的位置。我們選中節點后看到變換工具出現的位置就是節點的錨點位置。
錨點由 anchorX 和 anchorY 兩個值表示,他們是通過節點尺寸計算錨點位置的乘數因子,范圍都是 0 ~ 1 之間。(0.5, 0.5) 表示錨點位于節點長度乘 0.5 和寬度乘 0.5 的地方,即節點的中心。

錨點屬性設為 (0, 0) 時,錨點位于節點本地坐標系的初始原點位置,也就是節點約束框的左下角。

子節點的本地坐標系
錨點位置確定后,所有子節點就會以 錨點所在位置 作為坐標系原點,注意這個行為和 cocos2d-x 引擎中的默認行為不同,是 Cocos Creator 坐標系的特色!
假設場景中節點的結構如下圖所示:

當我們的場景中包含不同層級的節點時,我們按照以下的流程確定每個節點在世界坐標系下的位置:
從場景根級別開始處理每個節點,上圖中 NodeA 就是一個根級別節點。首先根據 NodeA 的 位置(Position) 屬性和 錨點(Anchor) 屬性,在世界坐標系中確定 NodeA 的顯示位置和坐標系原點位置(和錨點位置一致)。
接下來處理 NodeA 的所有直接子節點,也就是上圖中 NodeB 以及和 NodeB 平級的節點。根據 NodeB 的位置和錨點屬性,在 NodeA 的本地坐標系中確定 NodeB 在場景空間中的位置和坐標系原點位置。
之后不管有多少級節點,都繼續按照層級高低依次處理,每個節點都使用父節點的坐標系和自身位置錨點屬性來確定在場景空間中的位置。
變換屬性
除了上面介紹過的 錨點(Anchor) 之外,節點還包括四個主要的變換屬性,下面我們依次介紹。

位置(Position)
位置(Position) 由 x 和 y 兩個屬性組成,分別規定了節點在當前坐標系 x 軸和 y 軸上的坐標

上圖中節點 NodeA 位于場景根級別,他的位置是 (507, 354)(可以參考 場景編輯器 背景的刻度顯示),其子節點 NodeC 的位置是 (345, 0),可以看到子節點的位置是以父節點錨點為基準來偏移的。
位置屬性的默認值是 (0, 0),也就是說,新添加節點時,節點總會出現在父節點的坐標系原點位置。Cocos Creator 中節點的默認位置為 (0, 0),默認錨點設為 (0.5, 0.5)。這樣子節點會默認出現在父節點的中心位置,在制作 UI 或組合玩家角色時都能夠對所有內容一覽無余。
在場景編輯器中,可以隨時使用 移動變換工具 來修改節點位置。
旋轉(Rotation)
旋轉(Rotation) 是另外一個會對節點本地坐標系產生影響的重要屬性,旋轉屬性只有一個值,表示節點當前的旋轉角度。角度值為正時,節點順時針旋轉,角度值為負時,節點逆時針旋轉

上圖所示的節點層級關系和前一張圖相同,只是節點 NodeA 的 旋轉(Rotation) 屬性設為了 30 度,可以看到除了 NodeA 本身順時針旋轉了 30 度之外,其子節點 NodeC 也以 NodeA 的錨點為中心,順時針旋轉了 30 度。
在場景編輯器中,可以隨時使用 旋轉變換工具 來修改節點旋轉。
縮放(Scale)
縮放(Scale) 屬性也是一組乘數因子,由 scaleX 和 scaleY 兩個值組成,分別表示節點在 x 軸和 y 軸的縮放倍率。

上圖中節點 NodeA 的縮放屬性設為 (0.5, 1.0),也就是將該節點在 x 軸方向縮小到原來的 0.5 倍,y 軸保持不變。可以看到子節點 NodeC 圖像也在 x 軸方向上進行了壓縮,所以縮放屬性會影響所有子節點。
子節點上設置的縮放屬性會和父節點疊加作用,子節點的子節點會將每一層級的縮放屬性全部相乘來獲得在世界坐標系下顯示的縮放倍率,這一點和位置、旋轉其實是一致的,只不過位置和旋轉屬性是相加作用,只有縮放屬性是相乘,作用表現的更明顯。
縮放屬性是疊加在位置、尺寸等屬性上作用的,修改縮放屬性時,節點的位置和尺寸不會變化,但顯示節點圖像時會先將位置和尺寸等屬性和縮放相乘,得出的數值才是節點顯示的真實位置和大小。
在場景編輯器中,可以隨時使用 縮放變換工具 來修改節點縮放。
尺寸(Size)
尺寸(Size) 屬性由 Width(寬度)和 Height (高度)兩個值組成,用來規定節點的約束框大小。對于 Sprite 節點來說,約束框的大小也就相當于顯示圖像的大小。
因此尺寸屬性很容易和縮放屬性混淆,兩者都會影響 Sprite 圖像的大小,但他們是通過不同的方式來影響圖像實際顯示大小的。尺寸屬性和位置、錨點一起,規定了節點四個頂點所在位置,并由此決定由四個頂點約束的圖像顯示的范圍。尺寸屬性在渲染 九宮格圖像(Sliced Sprite) 時有至關重要的作用。
而縮放屬性是在尺寸數值的基礎上進行相乘,得到節點經過縮放后的寬度和高度。可以說在決定圖像大小時,尺寸是基礎,縮放是變量。另外尺寸屬性不會直接影響子節點的尺寸(但可以通過 對齊掛件(Widget)間接影響),這一點和縮放屬性有很大區別。
在場景編輯器中,可以隨時使用 矩形變換工具 來修改節點尺寸。