標准屏幕坐標系
如果接觸過iOS,Android,Windows Phone等系統的應用開發,或使用DOM,CSS開發過Web網頁,開發者會非常熟悉所謂的標准屏幕坐標系:左上角為原點,向右為X軸正方向,向下為Y軸正方向。
Cocos2d坐標系
Cocos2d引擎家族,包括Cocos2d-x,Cocos2d-JS的坐標系統是統一的,但是卻不同於前面的屏幕坐標系,而是繼承於OpenGL的右手笛卡爾坐標系(Right-handed Cartesian Coordinate System)。
Cocos2d坐標系的特點是:
- 原點為屏幕左下角
- 向右為X軸正方向
- 向上為Y軸正方向
錨點(Anchor Point)
錨點是在坐標系之上非常重要的概念,錨點就是給節點定位和仿射變換的基准點。錨點包含X軸和Y軸兩個方向上的基准點,兩個方向上的取值均為[0, 1],意味着錨點位置在節點的X軸和Y軸上的占其寬度和長度的比例。錨點的默認值對於cc.Layer
來說是(0,0),也就是場景的左下角;對於其他節點類型來說是(0.5,0.5),即節點的中央。
將一個節點添加到父節點里面時,需要設置其在父節點上的位置,本質上就是設置節點的錨點在父節點坐標系上的位置。節點的顯示位置是其位置屬性和錨點屬性共同作用的結果,位置屬性決定錨點位置,錨點屬性決定節點相對於錨點位置如何定位。以下圖為例:
圖中三個精靈的Y軸位置是相同的,左邊的精靈錨點為(0,0),所以錨點位於精靈的左下角;中間的精靈錨點為(0.5,0.5),所以錨點位於精靈 中央;右邊的精靈錨點為(1,1),所以錨點位於精靈右上角。與此同時,圖中可以看到,精靈的旋轉也是圍繞錨點的,所以錨點的作用不僅僅在於定位,它還會 影響針對節點做出的旋轉,防縮等操作。
忽略錨點
cc.Node
還擁有ignoreAnchor
屬性,默認值為false
,即使用錨點來定位。若改變其取值為true
,則在定位和仿射變換時忽略錨點,始終認為錨點為(0,0)。
Z值
cc.Node
包含兩種深度值:vertexZ
和zIndex
verextZ
是OpenGL坐標系中的Z值,僅在Web端的WebGL模式下或原生平台中有效。zIndex
是Cocos2d-JS本地坐標系中Z值。
在實際開發中開發者只需關注zIndex
,在本地坐標系中,即在某個節點的所有子結點中,它決定了子節點從前向后的排列以及繪制順序。zIndex
值越大,節點越靠前,反之,zIndex
值越小,節點越靠后,繪制順序則是從后向前逐個節點進行繪制,這也同樣符合右手笛卡爾坐標系的邏輯。
給節點定位
在Cocos2d-JS中,有兩個非常方便的屬性輔助開發者為某個節點定位:
cc.winSize
:Cocos2d-JS游戲窗口的大小。cc.visibleRect
:Cocos2d-JS游戲的可視范圍矩形以及相對於游戲窗口的位置等信息。
需要注意的是,cc.winSize
可能不等同於cc.visibleRect
的大小,這取決於游戲所使用的屏幕適配策略,關於屏幕適配策略的細節我們留待后面章節詳細闡述。概括來說,cc.winSize
等同於游戲場景的大小,但是游戲場景可能並不是完整可見,其可見范圍信息被保存在cc.visibleRect
中。cc.visibleRect
包含以下屬性:
屬性 | 類型 | 描述 |
---|---|---|
topLeft | Point | 可視范圍左上角坐標 |
topRight | Point | 可視范圍右上角坐標 |
bottomLeft | Point | 可視范圍左下角坐標 |
bottomRight | Point | 可視范圍右下角坐標 |
center | Point | 可視范圍中心點坐標 |
top | Point | 可視范圍上方中心點坐標 |
bottom | Point | 可視范圍下方中心點坐標 |
left | Point | 可視范圍左邊中心點坐標 |
right | Point | 可視范圍右邊中心點坐標 |
width | Number | 可視范圍的寬度 |
height | Number | 可視范圍的高度 |
舉個例子,想要在屏幕上方居中顯示一個精靈或文本標簽,那么可以使用cc.pAdd(cc.visibleRect.top, cc.p(0, 50))
來獲得上方中心點向下偏移50個像素的位置,這個位置就可以作為精靈的位置,同時將精靈的錨點設置為(0.5,1),那么這個精靈就會居中顯示,並且精靈頂端距離可視范圍頂端50個像素。
使用cc.winSize
配合cc.visibleRect
可以更有效率得為節點定位,我們強烈推薦配合錨點使用這些屬性來給節點進行定位。
設置錨點
var label = cc.LabelTTF.create("Hello World", "Arial", 40); label.setPosition(size.width / 2, size.height / 2);