cocos2dx中的座標系統

 

1、node

     (1)OpenGL座標系this

Cocos2D-x以OpenGL和OpenGL ES爲基礎,因此天然支持OpenGL座標系。該座標系原點在屏幕左下角,x軸向右,y軸向上。spa

(2)屏幕座標系.net

屏幕座標系使用的是不一樣的座標系統,原點在屏幕左上角,x軸向右,y軸向下。iOS的屏幕觸摸事件CCTouch傳入的位置信息使用的是該座標系。所以在Cocos2D-x中對觸摸事件作出響應前,須要首先把觸摸點轉化到OpenGL座標系。這一點在後面的觸屏信息中會詳細介紹,可使用CCDirector的convertToGL方法來完成這一轉化。orm

在處理觸摸事件的回調方法中,咱們會常常碰到這二者的座標系統的轉換處理問題。在CCTouch文件中已經爲咱們封裝好了獲取觸摸點在OpenGL座標系統和屏幕座標系統中的座標位置。對象

①從觸摸點獲取到在屏幕座標系中的座標blog

 

[cpp]  view plain copy
 
  1. // returns the current touch location in screen coordinates  
  2. CCPoint CCTouch::getLocationInView() const   
  3. {   
  4.     return m_point;   
  5. }  


②從觸摸點獲取到在OpenGL座標系中的座標遊戲

 

 

[cpp]  view plain copy
 
  1. // returns the current touch location in OpenGL coordinates  
  2. CCPoint CCTouch::getLocation() const  
  3. {   
  4.     return CCDirector::sharedDirector()->convertToGL(m_point);   
  5. }  

 

 

 

2、
(1)世界座標系統事件

 

世界座標系也叫做絕對座標系,是遊戲開發中創建的概念,所以,「世界」便是遊戲世界。它創建了描述其餘座標系所須要的參考標準。咱們可以用世界座標系來描述其餘座標系的位置。它是Cocos2D-x中一個比較大的概念。ip

Cocos2D-x中的元素是有父子關係的層級結構。經過CCNode設置位置使用的是相對其父節點的本地座標系,而非世界座標系。最後在繪製屏幕的時候,Cocos2D-x會把這些元素的本地節點座標映射成世界座標系座標。世界座標系和OpenGL座標系方向一致,原點在屏幕左下角,x軸向右,y軸向上。

 

(2)節點座標系統

 

節點座標系是和特定節點相關聯的座標系。每一個節點都有獨立的座標系。當節點移動或改變方向時,和該節點關聯的座標系(它的子節點)將隨之移動或改變方向。這一切都是相對的,相對於基準的,只有在節點座標系中才有意義。

CCNode類的設置位置使用的就是父節點的節點座標系。它和OpenGL座標系的方向也是一致的,x軸向右,y軸向上,原點在父節點的左下角。若是父節點是場景樹中的頂層節點,那麼它使用的節點座標系就和世界座標系重合了。

****

錨點

錨點指定了貼圖上和所在節點原點(也就是設置位置的點)重合的點的位置,所以只有在CCNode類節點使用貼圖的狀況下,錨點纔有意義。

錨點的默認值是(0.5,0.5),表示的並非一個像素點,而是一個乘數因子。(0.5,0.5) 表示錨點位於貼圖長度乘0.5和寬度乘0.5的地方,即貼圖的中心。

改變錨點的值雖然可能看起來節點的圖像位置發生了變化,但其實並不會改變節點的位置,其實變化的只是貼圖相對於你設置的位置的相對位置,至關於你在移動節點裏面的貼圖,而非節點自己。若是把錨點設置成(0,0),貼圖的左下角就會和節點的位置重合,這可能使得元素定位更爲方便,但會影響到元素的縮放和旋轉等一系列變換。所以並無一種錨點設置是放之四海而皆準的,要根據你這個對象的使用狀況來定義。在Cocos2D-x中錨點爲默認值(0.5,0.5),這樣的錨點設置要把一個節點放置到貼圖的中央。

****

 

上面關於世界座標系和節點座標系的介紹摘抄自Cocos2dx權威指南一書,下面我簡單通俗的講解一下個人理解:

其實,兩者之間是一個絕對和相對的概念,世界座標系是絕對的,而節點座標系是相對的。

能夠這樣理解世界座標系,所謂絕對,其實它就是和OpenGL座標系(等同)一致的座標系統,原點在屏幕左下角,x軸方向向右,y軸方向向上。

而節點座標系是相對於具體的節點來講的,每個物體都有一個特定的座標系統,當節點移動時,那麼它自己的座標系統也就跟着發生變化。可是有一點須要特別注意:節點座標系的原點默認是其左下角位置。

例如說:咱們在一個layer中添加一個sprite,錨點爲(0,0),size爲(40,40),位置爲(50,50),那麼此時這個sprite的節點座標系統是神馬呢? ------- 這時它的節點座標系統就是以(50,50)爲座標系統原點,x軸向右,y軸向上的座標系。

對上面的例子稍稍變一下:錨點位置改成(0.5,0.5),其餘不變,那麼這個時候sprite的節點座標系統又是多少呢?(注意到上面的:節點座標系的原點默認是其左下角位置) ----- 這個時候它的節點座標系統就是以(30,30)爲座標系統原點,x軸向右,y軸向上的座標系。

這樣理解是否好一些呢?(若有不對之處,歡迎評論指正!)

 

關於這兩個座標系統之間的轉換,在CCNode中定義瞭如下四個經常使用的座標變換的相關方法。

 

[cpp]  view plain copy
 
  1. /**  
  2.      * Converts a Point to node (local) space coordinates. The result is in Points. 
  3.      */  
  4.     CCPoint convertToNodeSpace(const CCPoint& worldPoint);  
  5.       
  6.     /**  
  7.      * Converts a Point to world space coordinates. The result is in Points. 
  8.      */  
  9.     CCPoint convertToWorldSpace(const CCPoint& nodePoint);  
  10.       
  11.     /**  
  12.      * Converts a Point to node (local) space coordinates. The result is in Points. 
  13.      * treating the returned/received node point as anchor relative. 
  14.      */  
  15.     CCPoint convertToNodeSpaceAR(const CCPoint& worldPoint);  
  16.       
  17.     /**  
  18.      * Converts a local Point to world space coordinates.The result is in Points. 
  19.      * treating the returned/received node point as anchor relative. 
  20.      */  
  21.     CCPoint convertToWorldSpaceAR(const CCPoint& nodePoint);  

 

 

 

convertToWorldSpace:把基於當前節點的本地座標系下的座標轉換到世界座標系中。

convertToNodeSpace:把世界座標轉換到當前節點的本地座標系中。

這兩種轉換都是不考慮錨點的,都以當前節點父類的左下角的座標爲標準。另外,CCNode還提供了convertToWorldSpaceAR和convertToNodeSpaceAR。這兩個方法完成一樣的功能,可是它們的基準座標是基於座標錨點的。幾乎全部的遊戲引擎都會使用相似的本地座標系而非世界座標系來指定元素的位置。

這樣作的好處是,當計算物體運動的時候,使用同一本地座標系的元素能夠做爲一個子系統獨立計算,最後再加上座標系的運動便可,這是物理研究中經常使用的思路。例如,一個在行駛的車箱內上下跳動的人,只須要在每幀繪製的時候計算他在車箱座標系中的位置,而後加上車的位置就能夠計算出人在世界座標系中的位置。若是使用單一的世界座標系,人的運動軌跡就變複雜了,就涉及中學所學到的運動軌跡的合成與分解。

 

上面的解釋也是來自Cocos2dx權威指南一書,下面我經過一個例子來講明這四個方法的理解和做用。

一、convertToNodeSpace  和  convertToWorldSpace

 

[cpp]  view plain copy
 
  1. CCSprite *sprite1 = CCSprite::create("CloseNormal.png");  
  2.     sprite1->setPosition(ccp(20,40));  
  3.     sprite1->setAnchorPoint(ccp(0,0));  
  4.     this->addChild(sprite1);  //此時添加到的是世界座標系,也就是OpenGL座標系  
  5.       
  6.     CCSprite *sprite2 = CCSprite::create("CloseNormal.png");  
  7.     sprite2->setPosition(ccp(-5,-20));  
  8.     sprite2->setAnchorPoint(ccp(1,1));  
  9.     this->addChild(sprite2); //此時添加到的是世界座標系,也就是OpenGL座標系  
  10.       
  11.     //將 sprite2 這個節點的座標ccp(-5,-20) 轉換爲 sprite1節點 下的本地(節點)座標系統的 位置座標  
  12.     CCPoint point1 = sprite1->convertToNodeSpace(sprite2->getPosition());  
  13.       
  14.     //將 sprite2 這個節點的座標ccp(-5,-20) 轉換爲 sprite1節點 下的世界座標系統的 位置座標  
  15.     CCPoint point2 = sprite1->convertToWorldSpace(sprite2->getPosition());  
  16.       
  17.     CCLog("position = (%f,%f)",point1.x,point1.y);  
  18.     CCLog("position = (%f,%f)",point2.x,point2.y);  


運行結果:

 

 

[cpp]  view plain copy
 
  1. Cocos2d: position = (-25.000000,-60.000000)  
  2. Cocos2d: position = (15.000000,20.000000)  


                               

 

下面解釋一下:咱們添加了兩個節點sprite1(node1),sprite2(node2)。

其中 : CCPoint point1 = sprite1->convertToNodeSpace(sprite2->getPosition()); 

至關於咱們將sprite2這個節點添加到(實際沒有添加,只是這樣理解)sprite1這個節點上,那麼就須要使用sprite1這個節點的節點座標系統,這個節點的節點座標系統的原點在(20,40),而sprite1的座標是(-5,-20),那麼通過變換以後,sprite1的座標就是(-25,-60)。

其中 : CCPoint point2 = sprite1->convertToWorldSpace(sprite2->getPosition());

此時的變換是將sprite2的座標轉換到sprite1的世界座標系下,而其中世界座標系是沒有變化的,始終都是和OpenGL等同,只不過sprite2在變換的時候將sprite1做爲了」參照「而已。因此變換以後sprite2的座標爲:(15,20)

通俗一點理解就是,sprite2的座標在sprite1節點左下角(原點)座標的基礎上加上sprite2的座標(也即基於sprite1原點的平移,平移座標就是sprite1的ccp(-5,-20))就能夠獲得sprite2變換後的座標:(15,20)=sprite1原點座標(20,40)+ 平移(-5,-20)

 

二、convertToNodeSpaceAR  和  convertToWorldSpaceAR

注意到這兩個方法只不過增長了AR的約束,也即錨點。其意思是:修改變換的基準。這樣理解:

convertToNodeSpaceAR,就是將節點座標系的座標原點修改在其錨點位置。(convertToNodeSpace 節點座標系的原點位置是其左下角)

convertToWorldSpaceAR,就是在變換的時候將參照座標修改到其錨點位置。(convertToWorldSpace 參照座標是在其左下角)

下面給出一個例子說明一下這兩個方法:

 

[cpp]  view plain copy
 
  1. CCSprite *sprite1 = CCSprite::create("CloseNormal.png");  
  2.     sprite1->setPosition(ccp(100,100));  
  3.     sprite1->setAnchorPoint(ccp(0.5,0.5));  
  4.     this->addChild(sprite1);  
  5.       
  6.     CCSprite *sprite2 = CCSprite::create("CloseNormal.png");  
  7.     sprite2->setPosition(ccp(-5,-20));  
  8.     sprite2->setAnchorPoint(ccp(1,1));  
  9.     this->addChild(sprite2);  
  10.       
  11.     CCPoint point3 = sprite1->convertToNodeSpaceAR(sprite2->getPosition());  
  12.     CCPoint point4 = sprite1->convertToWorldSpaceAR(sprite2->getPosition());  
  13.       
  14.     CCLog("position = (%f,%f)",point3.x,point3.y);  
  15.     CCLog("position = (%f,%f)",point4.x,point4.y);  


運行結果:

 

 

[cpp]  view plain copy
 
  1. Cocos2d: position = (-105.000000,-120.000000)  
  2. Cocos2d: position = (95.000000,80.000000)  

 

 

首先關於 convertToNodeSpaceAR 咱們能夠用下面這個圖來看。

sprite1節點的節點座標系原點如今變成節點的錨點所在位置,在這個位置創建一個座標系,那麼就能夠肯定sprite2轉換到這個節點座標系所在的位置了。

 

而關於  convertToWorldSpaceAR  其實其變換和  convertToWorldSpace 是十分相似的,只不過其原點變成其節點的錨點,而不是左下角。

那麼變換的過程: sprite2變換後的座標(90,80) = sprite1的錨點(100,100) + 平移(-5,-20)。

轉自:http://blog.csdn.net/crayondeng/article/details/11936309

相關文章
相關標籤/搜索