支持以下幾種坐標系:
1.屏幕坐標系 原點在左上角,X軸向右,Y軸向下。
2.GL坐標系 原點在左下角,X軸向右,Y軸向上。
3.世界坐標系 指相對於整個屏幕的坐標系,(0,0)就是屏幕的左下角,(320,480)就是屏幕的右上角。
4.本地坐標系 相對於父對象的坐標。
[obj.parent convertToWorldSpace:[obj position]]; //獲得obj的世界坐標 [obj.parent convertToNodeSpace:[obj position]]; //獲得obj的本地坐標 [[CCDirector sharedDirector] convertToGL:*****(0,0)]; //獲得GL坐標 [[CCDirector sharedDirector] convertToUI:*****(0,0)]; //獲得屏幕坐標
錨點(anchor):
錨點是對象的坐標參考點,比方說 如果你要把一個門牌釘在門上,那么那顆釘子就是門牌的錨點,之后設置position時將會相對於錨點來設置。
obj.anchor = *****(0,0) //obj的錨點是左下角 obj.position = *****(0,0) //此時 obj會以它的左下角會參考點貼在父對象的左下角
這里要注意的是 CCLayer默認是禁用錨點的,即使你設置了它的錨點也根沒設置一樣!你需要使用以下代碼開啟它對錨點的支持:
[obj setIsRelativeAnchorPoint:YES]; //啟用 obj 的錨點
無論是搞2d還是3d開發,最需要搞清楚的就是坐標系,這部分混亂的話就沒啥奔頭了。所以玩cocos2d,一上來就先把各種與坐標有關的東西搞清楚。
基本的兩個坐標系:屏幕坐標系和GL坐標系。
屏幕坐標系x軸朝右,y軸朝下。默認原點在左上角。
GL坐標系x軸朝右,y軸朝上。默認原點在左下角。
在調用任何需要設置位置的函數,或從函數獲取位置信息前,必須要明確這個函數使用哪個坐標系。比如調用CCNode類的setPosition函數,它使用的就是GL坐標系。比如在處理觸摸事件時CCTouch對象中的坐標就是屏幕坐標系。
另一個重要的坐標系就是和Node相關的本地坐標系。這個結構和一般做3D用的場景樹的概念是一樣的。所以從Node拿到的位置是該節點的本地坐標,需要通過特定的函數才能把本地坐標轉換為世界坐標。而且這里的坐標都用的是GL坐標系。在CCNode對象中有幾個方便的函數可以做坐標轉換。convertToWorldSpace方法可以把基於當前node的本地坐標系下的坐標轉換到世界坐標系中。convertToNodeSpace方法可以把世界坐標轉換到當前node的本地坐標系中。
另一個關鍵的問題就是在cocos2d里面就是各種對象的大小問題。因為在cocos2d里CCNode對象有縮放的方法setScaleX和setScaleY。所以在獲取對象大小的時候就必須根據情況明確指定獲取對象原始大小,還是縮放后的大小。當然cocos2d里提供了對應的函數來完成這些操作。
getContentSize 函數用來獲得節點原始的大小。
boundingBox 函數用來獲得經過縮放和旋轉之后的外框盒大小。
舉個簡單的例子:
bool ret = CCRect::CCRectContainsPoint(
this->boundingBox() , this->getParent()->convertTouchToNodeSpace( pTouch ));
這個例子的功能是來判定當前的觸摸操作是否發生在自己的node對象上。其中pTouch是CCTouch對象的指針,包含了當前觸摸事件發生點的坐標。
CCRectContainsPoint這個函數用來判斷一個點是否在一個矩形范圍內。我們就想用這個函數來判斷當前觸摸操作的這個點是否在當前node的范圍內。
this->boundingBox() 方法獲得了當前節點對象在父節點對象下的縮放之后的本地坐標大小,並且是用GL坐標系表示的。
pTouch對象中的坐標是屏幕坐標系,所以必須轉換到GL坐標系,再轉換到父節點的本地坐標下。好在convertTouchToNodeSpace這個函數一次完成了這兩個轉換,可以參考該庫的源碼,其中有具體的計算過程。
所有數據都轉換到同一個坐標系下了以后,就可以通過CCRectContainsPoint函數完成最終的判定操作。
最后想說的一點是,盡可能用相對坐標。換句話說,程序中所有對象在設置大小和位置時,都應該以父對象的大小和位置為依據。 這樣程序發布在以各種不同的分辨率發布時,只需要調整根對象的大小就可以了。