Cocos2d-x坐标系介绍
在图形图像和游戏应用开发中坐标系是非常重要的我们在Android和iOS等平台应用开发的时候使用的二维坐标系它的原点是在左上角的。而在Cocos2d-x坐标系中它原点是在左下角的而且Cocos2d-x坐标系又可以分为世界坐标和模型坐标。
UI坐标
UI坐标就是Android和iOS等应用开发的时候使用的二维坐标系。它的原点是在左上角的。
UI坐标原点是在左上角x轴向右为正y轴向下为正。我们在Android和iOS等平台使用的视图、控件等都是遵守这个坐标系。然而在Cocos2d-x默认不是采用UI坐标但是有的时候也会用到UI坐标例如在触摸事件发生的时候我们会获得一个触摸对象Touch触摸对象Touch提供了很多获得位置信息的函数如下面代码所示
Point touchLocation = touch->getLocationInView();
使用getLocationInView()函数获得触摸点坐标事实上就是UI坐标它的坐标原点在左上角。而不是Cocos2d-x默认坐标我们可以采用下面的语句进行转换
Point touchLocation2 = Director::getInstance()->convertToGL(touchLocation);
通过上面的语句就可以将触摸点位置从UI坐标转换为OpenGL坐标OpenGL坐标就是Cocos2d-x默认坐标。
OpenGL坐标
我们在上面提到了OpenGL坐标OpenGL坐标是种三维坐标。由于Cocos2d-x底层采用OpenGL渲染因此的默认坐标就是OpenGL坐标只不过只采用两维x和y轴。如果不考虑z轴OpenGL坐标的原点在左下角。
提示: 三维坐标根据z轴的指向不同分为左手坐标和右手坐标。右手坐标是z轴指向屏幕外。左手坐标是z轴指向屏幕里.OpenGL坐标是右手坐标而微软平台的Direct3D[1]是左手坐标。
世界坐标和模型坐标
由于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像素。这里的坐标事实上就是世界坐标它的坐标原点是屏幕的左下角。
编写代码如下
bool HelloWorld::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, origin.y+ visibleSize.height/2)); this->addChild(bg,0); ② //创建Node1 autonode1 = Sprite::create("node1.png"); ③ node1->setPosition(Point(400,500)); node1->setAnchorPoint(Point(1.0,1.0)); this->addChild(node1,0); ④ //创建Node2 autonode2 = Sprite::create("node2.png"); ⑤ node2->setPosition(Point(200,300)); node2->setAnchorPoint(Point(0.5,0.5)); this->addChild(node2,0); ⑥ PointPoint1 = node1->convertToNodeSpace(node2->getPosition()); ⑦ PointPoint3 = node1->convertToNodeSpaceAR(node2->getPosition()); ⑧ log("Node2NodeSpace = (%f,%f)",Point1.x,Point1.y); log("Node2NodeSpaceAR = (%f,%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、模型坐标转换为世界坐标
下面是模型坐标转换为世界坐标实例运行结果。
在游戏场景中有两个Node对象其中Node1的坐标是(400, 500)大小是300 x 100像素。Node2是放置在Node1中的它对于Node1的模型坐标是(0, 0)大小也是150 x 50像素。
编写代码如下
bool HelloWorld::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, origin.y+ visibleSize.height/2)); this->addChild(bg,0); //创建Node1 autonode1 = Sprite::create("node1.png"); node1->setPosition(Point(400,500)); this->addChild(node1,0); //创建Node2 autonode2 = Sprite::create("node2.png"); node2->setPosition(Point(0.0,0.0)); ① node2->setAnchorPoint(Point(0.0,0.0)); ② node1->addChild(node2,0); ③ PointPoint2 = node1->convertToWorldSpace(node2->getPosition()); ④ Point Point4 =node1->convertToWorldSpaceAR(node2->getPosition()); ⑤ log("Node2WorldSpace = (%f,%f)",Point2.x,Point2.y); log("Node2WorldSpaceAR = (%f,%f)",Point4.x,Point4.y); returntrue; }
上述代码我们主要关注第③行它是将Node2放到Node1中这是与之前的代码的区别。这样第①行设置的坐标就变成了相对于Node1的模型坐标了。
第④行代码将Node2的模型坐标转换为世界坐标。而第⑤行代码是类似的它是相对于锚点的位置。
运行结果如下
Node2 WorldSpace =(250.000000,450.000000)
Node2 WorldSpaceAR =(400.000000,500.000000)
所示的位置可以用世界坐标描述。代码①~③行修改如下
node2->setPosition(Point(250, 450));
node2->setAnchorPoint(Point(0.0,0.0));
this->addChild(node2, 0);
[1] Direct3D简称D3D是微软公司在Microsoft Windows操作系统上所开发的一套3D绘图编程接口是DirectX的一部份目前广为各家显卡所支持。与OpenGL同为计算机绘图软件和计算机游戏最常使用的两套绘图编程接口之一。—— 引自于维基百科 https://zh.wikipedia.org/wiki/Direct3D
《Cocos2d-x实战 C++卷》现已上线各大商店均已开售
京东https://item.jd.com/11584534.html
当当https://product.dangdang.com/23606265.html
互动出版网https://product.china-pub.com/3770734
《Cocos2d-x实战 C++卷》源码及样章下载地址
源码下载地址https://51work6.com/forum.php?mod=viewthread&tid=1155&extra=page%3D1
样章下载地址https://51work6.com/forum.php?mod=viewthread&tid=1157&extra=page%3D1

最后更新:2017-04-03 12:56:32