http://blog.csdn.net/tonny_guan/article/details/25117341?utm_source=tuicool
在图形图像和游戏应用开发中坐标系是非常重要的,我们在Android和iOS等平台应用开发的时候使用的二维坐标系它的原点是在左上角的。而在Cocos2d-x坐标系中它原点是在左下角的,而且Cocos2d-x坐标系又可以分为:世界坐标和模型坐标。
UI坐标
UI坐标就是Android和iOS等应用开发的时候使用的二维坐标系。它的原点是在左上角的。
UI坐标原点是在左上角,x轴向右为正,y轴向下为正。我们在Android和iOS等平台使用的视图、控件等都是遵守这个坐标系。然而在Cocos2d-x默认不是采用UI坐标,但是有的时候也会用到UI坐标,例如在触摸事件发生的时候,我们会获得一个触摸对象(Touch),触摸对象(Touch)提供了很多获得位置信息的函数,如下面代码所示:
PointtouchLocation = touch->getLocationInView();
使用getLocationInView()函数获得触摸点坐标事实上就是UI坐标,它的坐标原点在左上角。而不是Cocos2d-x默认坐标,我们可以采用下面的语句进行转换:
PointtouchLocation2 = Director::getInstance()->convertToGL(touchLocation);
通过上面的语句就可以将触摸点位置从UI坐标转换为OpenGL坐标,OpenGL坐标就是Cocos2d-x默认坐标。
OpenGL坐标
我们在上面提到了OpenGL坐标,OpenGL坐标是种三维坐标。由于Cocos2d-x底层采用OpenGL渲染,因此的默认坐标就是OpenGL坐标,只不过只采用两维(x和y轴)。如果不考虑z轴,OpenGL坐标的原点在左下角。
世界坐标和模型坐标
由于OpenGL坐标有可以分为:世界坐标和模型坐标,所以Cocos2d-x的坐标也有世界坐标和模型坐标。
你是否有过这样的问路经历:张三会告诉你向南走一公里,再向东走500米。而李四会告诉你向右走一公里,再向左走500米。这里两种说法或许都可以找到你要寻找的地点。张三采用的坐标是世界坐标,他把地球作为参照物,表述位置使用地理的东、南、西和北。而李四采用的坐标是模型坐标,他让你自己作为参照物,表述位置使用你的左边、你的前边、你的右边和你的后边。
我们看看图3-21,从图中可以看到A的坐标是(5,5),B的坐标是(4,6),事实上这些坐标值就是世界坐标。如果采用A的模型坐标来描述B的位置,则B的坐标是(1,-1)。
有的时候我们需要将世界坐标与模型坐标互相转换。我们可以通过Node对象如下函数实现:
Point convertToNodeSpace ( const Point & worldPoint )。将世界坐标转换为模型坐标。
Point convertToNodeSpaceAR ( const Point & worldPoint )。将世界坐标转换为模型坐标。AR表示相对于锚点。
Point convertTouchToNodeSpace ( Touch * touch )。将世界坐标中触摸点转换为模型坐标。
Point convertTouchToNodeSpaceAR ( Touch * touch )。将世界坐标中触摸点转换为模型坐标。AR表示相对于锚点。
Point convertToWorldSpace ( const Point & nodePoint )。将模型坐标中触摸点转换为世界坐标。
Point convertToWorldSpaceAR ( const Point & nodePoint )。将模型坐标中触摸点转换为世界坐标。AR表示相对于锚点。
下面我们通过两个例子了解一下世界坐标与模型坐标互相转换。
1、世界坐标转换为模型坐标
下面是世界坐标转换为模型坐标实例运行结果。
在游戏场景中有两个Node对象,其中Node1的坐标是(400,500),大小是300 x 100像素。Node2的坐标是(200,300),大小也是300 x 100像素。这里的坐标事实上就是世界坐标,它的坐标原点是屏幕的左下角。
编写代码如下:
- boolHelloWorld::init()
- {
- if(!Layer::init())
- {
- returnfalse;
- }
- SizevisibleSize=Director::getInstance()->getVisibleSize();
- Pointorigin=Director::getInstance()->getVisibleOrigin();
- autocloseItem=MenuItemImage::create(
- "CloseNormal.png",
- "CloseSelected.png",
- CC_CALLBACK_1(HelloWorld::menuCloseCallback,this));
- closeItem->setPosition(Point(origin.x+visibleSize.width-closeItem->getContentSize().width/2,
- origin.y+closeItem->getContentSize().height/2));
- automenu=Menu::create(closeItem,NULL);
- menu->setPosition(Point::ZERO);
- this->addChild(menu,1);
- //创建背景
- autobg=Sprite::create("bg.png");①
- bg->setPosition(Point(origin.x+visibleSize.width/2,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> origin.y+visibleSize.height/2));
- >addChild(bg,0);②
- //创建Node1
- autonode1=Sprite::create("node1.png");③
- node1->setPosition(Point(400,500));
- node1->setAnchorPoint(Point(1.0,1.0));
- >addChild(node1,0);④
- //创建Node2
- autonode2=Sprite::create("node2.png");⑤
- node2->setPosition(Point(200,300));
- node2->setAnchorPoint(Point(0.5,0.5));
- >addChild(node2,0);⑥
- PointPoint1=node1->convertToNodeSpace(node2->getPosition());⑦
- PointPoint3=node1->convertToNodeSpaceAR(node2->getPosition());⑧
- log("Node2NodeSpace=(%f,%f)",Point1.x,Point1.y);
- log("Node2NodeSpaceAR=(%f,Point3.x,Point3.y);
- returntrue;
- }
代码①~②行是创建背景精灵对象,这个背景是一个白色900 x 640像素的图片。代码第③~④行是创建Node1对象,并设置了位置和锚点属性。代码第⑤~⑥行是创建Node2对象,并设置了位置和锚点属性。第⑦行代码将Node2的世界坐标转换为相对于Node1的模型坐标。而第⑧行代码是类似的,它是相对于锚点的位置。
运行结果如下:
Node2 NodeSpace = (100.000000,-100.000000)
Node2 NodeSpaceAR =(-200.000000,-200.000000)
Node2的世界坐标转换为相对于Node1的模型坐标,就是将Node1的左下角作为坐标原点(图3-22中的A点),我们不难计算出A点的世界坐标是(100,400),那么convertToNodeSpace函数就是A点坐标减去C点坐标,结果是(-100,100)。而convertToNodeSpaceAR函数要考虑锚点,因此坐标原点是B点,B点坐标减去C点坐标,结果是(-200,-200)。
2、模型坐标转换为世界坐标
下面是模型坐标转换为世界坐标实例运行结果。