坐标笔记
UI坐标
UI坐标就是Android和iOS等应用开发的时候使用的二维坐标系。它的原点是在左上角的。
UI坐标原点是在左上角,x轴向右为正,y轴向下为正。我们在Android和iOS等平台使用的视图、控件等都是遵守这个坐标系。然而在Cocos2d-x默认不是采用UI坐标,但是有的时候也会用到UI坐标,例如在触摸事件发生的时候,我们会获得一个触摸对象(Touch),触摸对象(Touch)提供了很多获得位置信息的函数,如下面代码所示:
CCPoint touchLocation = touch->getLocationInView();
使用getLocationInView()函数获得触摸点坐标事实上就是UI坐标,它的坐标原点在左上角,而不是Cocos2d-x默认坐标,我们可以采用下面的语句进行转换:
CCPoint touchLocation2 = CCDirector::sharedDirector()->convertToGL(touchLocation);
通过上面的语句就可以将触摸点位置从UI坐标转换为OpenGL坐标,OpenGL坐标就是Cocos2d-x默认坐标。
OpenGL坐标
OpenGL坐标是种三维坐标。由于Cocos2d-x底层采用OpenGL渲染,因此的默认坐标就是OpenGL坐标,只不过只采用两维(x和y轴)。如果不考虑z轴,OpenGL坐标的原点在左下角,x轴向右为正,y轴向上为正。
世界坐标和模型坐标
由于OpenGL坐标有可以分为:世界坐标和模型坐标,所以Cocos2d-x的坐标也有世界坐标和模型坐标。
有的时候我们需要将世界坐标与模型坐标互相转换。我们可以通过Node对象如下函数实现:
CCPoint convertToNodeSpace ( const CCPoint& worldPoint )。将世界坐标转换为模型坐标。
CCPoint convertToNodeSpaceAR ( const CCPoint& worldPoint )。将世界坐标转换为模型坐标。AR表示相对于锚点。
CCPoint convertTouchToNodeSpace ( CCTouch *touch )。将世界坐标中触摸点转换为模型坐标。
CCPoint convertTouchToNodeSpaceAR ( CCTouch *touch )。将世界坐标中触摸点转换为模型坐标。AR表示相对于锚点。
CCPoint convertToWorldSpace ( const CCPoint& worldPoint )。将模型坐标中触摸点转换为世界坐标。
CCPoint convertToWorldSpaceAR ( const CCPoint& worldPoint )。将模型坐标中触摸点转换为世界坐标。AR表示相对于锚点。
通过例子了解一下世界坐标与模型坐标互相转换。
1、世界坐标转换为模型坐标
在游戏场景中有两个Node对象,其中Node1的坐标是B(240, 160),大小是120 x 40像素。Node2的坐标是C(80, 80),大小也是120 x 40像素。这里的坐标事实上就是世界坐标,它的坐标原点是屏幕的左下角。
编写代码如下:
bool HelloWorld::init() { bool bRet = false; do { CC_BREAK_IF(! CCLayerColor::initWithColor(ccc4(255, 255, 255, 255))); CCSprite* pNode1 = CCSprite::create("node1.jpg"); pNode1->setPosition(ccp(240, 160)); pNode1->setAnchorPoint(ccp(1, 1)); this->addChild(pNode1, 0); CCSprite* pNode2 = CCSprite::create("node2.jpg"); pNode2->setPosition(ccp(80, 80)); pNode2->setAnchorPoint(ccp(0.5, 0.5)); this->addChild(pNode2, 0); CCPoint ponit1 = pNode1->convertToNodeSpace(pNode2->getPosition()); CCPoint ponit2 = pNode1->convertToNodeSpaceAR(pNode2->getPosition()); CCLog("Node2 NodeSpace = (%f,%f)",ponit1.x,ponit1.y); CCLog("Node2 NodeSpaceAR = (%f,%f)",ponit2.x,ponit2.y); bRet = true; } while (0); return bRet; }
运行结果如下:
Node2 NodeSpace = (-40.000000,-40.000000)
Node2 NodeSpaceAR = (-160.000000,-80.000000)
Node2的世界坐标转换为相对于Node1的模型坐标,就是将Node1的左下角作为坐标原点(图中的A点),A点的世界坐标是(240-120,160-40),那么convertToNodeSpace函数就是C(80, 80)点坐标减去A(120,120)点坐标,结果是(-40,-40)。而convertToNodeSpaceAR函数要考虑锚点,因此坐标原点是B点,C(80, 80)点坐标减去B(240, 160)点坐标,结果是(-160, -80)。
2、模型坐标转换为世界坐标
在游戏场景中有两个Node对象,其中Node1的坐标是B(240, 160),大小是120 x 40像素。Node2是放置在Node1中的,它对于Node1的模型坐标是C(0, 0),大小60 x 20像素。
编写代码如下:
bool HelloWorld::init() { bool bRet = false; do { CC_BREAK_IF(! CCLayerColor::initWithColor(ccc4(255, 255, 255, 255))); CCSprite* pNode1 = CCSprite::create("node1.jpg"); pNode1->setPosition(ccp(240, 160)); pNode1->setAnchorPoint(ccp(1, 1)); this->addChild(pNode1, 0); CCSprite* pNode2 = CCSprite::create("node2.jpg"); pNode2->setPosition(ccp(0, 0)); pNode2->setAnchorPoint(ccp(0, 0)); pNode1->addChild(pNode2, 0); CCPoint ponit1 = pNode1->convertToWorldSpace(pNode2->getPosition()); CCPoint ponit2 = pNode1->convertToWorldSpaceAR(pNode2->getPosition()); CCLog("Node2 WorldSpace = (%f,%f)",ponit1.x,ponit1.y); CCLog("Node2 WorldSpaceAR = (%f,%f)",ponit2.x,ponit2.y); bRet = true; } while (0); return bRet; }
运行结果如下:
Node2 WorldSpace = (120.000000,120.000000)
Node2 WorldSpaceAR = (240.000000,160.000000)
Node2的模型坐标转换为相对于Node1的世界坐标,就是将Node1的左下角作为坐标原点(图中的A点),A世界坐标是(240-120,160-40),那么convertToWorldSpace函数就是C(0,0)点坐标加上A(120,120)点坐标,结果是(120,120)。而convertToWorldSpaceAR函数要考虑锚点,因此坐标原点是B点,C(0,0)点坐标加上B(240,160)点坐标,结果是(240,160)。