cocos2dx坐标转换_许彦峰的博客-程序员秘密

技术标签: 技术  

http://blog.sina.com.cn/s/blog_4dc0f99c01019hlr.html

用到cocos2d的坐标转换,一般两种情况:
1)从当前坐标点获取世界坐标点(屏幕坐标点,opengl的坐标系)
2)从当前坐标点获取相对于某个CCNode的坐标点;
第一种情况,直接用:nodeParent->convertToWorldSpace(node->getPosition());
这里一定是需要转换坐标对象的父类调用convertToWorldSpace,参数是对象的坐标点(相对于父类的坐标点);
返回的是屏幕坐标点;
第二种情况,直接用:node2->convertToNodeSpace(node1->getPosition);
node2并不是node1的父类,现在的情况就是:node1想得到相对于node2坐标系的坐标点;
返回的是相对于node2坐标系的坐标点。
以上的调用,是没有考虑nodeParent和node2的anchorPoint的(就是使用了0,0的锚点);考虑到锚点就使用:
convertToWorldSpaceAR()和convertToNodeSpaceAR();具体含义了?
nodeParent->convertToWorldSpaceAR(node->getPosition()):因为默认是0,0的锚点,
所以其得到的坐标点是ccpAdd(nodeParent->convertToWorldSpace(node->getPosition()),ccp(nodeParent->getContentSize.width*0.5,nodeParent->getContentSize.height*0.5))
node2->convertToNodeSpaceAR(node1->getPosition):因为默认是0,0的锚点,
所以其得到的坐标点是ccpSub(nodeParent->convertToWorldSpace(node->getPosition()),ccp(node2->getContentSize.width*0.5,node2->getContentSize.height*0.5))


对cocos2d-x里面的四个表示坐标的方法进行了一下研究,特意做了下笔记,如下:
CCPoint convertToNodeSpace(const CCPoint& worldPoint);
CCPoint convertToWorldSpace(const CCPoint& nodePoint);
CCPoint convertToNodeSpaceAR(const CCPoint& worldPoint);
CCPoint convertToWorldSpaceAR(const CCPoint& nodePoint);

在理解这个之前,要多世界坐标和本地坐标有一定的理解,
GL坐标系Cocos2D以OpenglES为图形库,所以它使用OpenglES坐标系。GL坐标系原点在屏幕左下角,x轴向右,y轴向上。

 

屏幕坐标系苹果的Quarze2D使用的是不同的坐标系统,原点在屏幕左上角,x轴向右,y轴向下。ios的屏幕触摸事件CCTouch传入的位置信息使用的是该坐标系。因此在cocos2d中对触摸事件做出响应前需要首先把触摸点转化到GL坐标系。可以使用CCDirector的convertToGL来完成这一转化。

 

世界坐标系也叫做绝对坐标系,cocos2d中的元素是有父子关系的层级结构,我们通过CCNode的position设定元素的位置使用的是相对与其父节点的本地坐标系而非世界坐标系。最后在绘制屏幕的时候cocos2d会把这些元素的本地坐标映射成世界坐标系坐标。世界坐标系和GL坐标系一致,原点在屏幕左下角,

本地坐标系本地坐标系也叫做物体坐标系,是和特定物体相关联的坐标系。每个物体都有它们独立的坐标系,当物体移动或改变方向时,和该物体关联的坐标系将随之移动或改变方向。比如用cocos2d-x创建了个矩形colorLayer:CCRect(10,10,100,100),这是的本地坐标系为以(10,10)为坐标原点,x轴向右,y轴向上。如果创建了一个CCSprite,锚点为(0.5,0.5),位置为(100,100),size为(40,40),这时的本地坐标系为以(80,80)为坐标原点,x轴向右,y轴向上。总之,本地坐标系原点为node的左下角坐标


接下来,convertToNodeSpace:调用CCPoint point = node1->convertToNodeSpace(node2->getPosition());

将node2的坐标转化成相对于node1的本地坐标

 

cocos2d-x 坐标研究 - zjfzjf - zjfzjf
 ,
比如坐标如上图所示,node1的锚点为(0,0),node2的锚点为(1,1),转化之后,node的坐标变成了(-25,-60)

convertToWorldSpace:调用CCPoint point = node1->convertToWorldSpace(node2->getPosition());
cocos2d-x 坐标研究 - zjfzjf - zjfzjf
 
是将node的坐标转化成相对于node1的世界坐标,如上图所示:首先将node1的坐标当做世界坐标,然后让node2的坐标位置重置成相对于node1的世界坐标,也就是(15,20)

convertToNodeSpaceAR就是把node1的坐标系原点设置在锚点的位置,这里的锚点是(0,0)所以转化之后的坐标系位置和上面的convertToNodeSpace一样,结果也是一样的,convertToWorldSpaceAR同理


测试:
CCSprite *sprite1 = CCSprite::spriteWithFile("CloseNormal.png");
sprite1->setPosition(ccp(20,40));
sprite1->setAnchorPoint(ccp(0,0));
this->addChild(sprite1);
CCSprite *sprite2 = CCSprite::spriteWithFile("CloseNormal.png");
sprite2->setPosition(ccp(-5,-20));
sprite2->setAnchorPoint(ccp(1,1));
this->addChild(sprite2);
CCPoint point1 = sprite1->convertToNodeSpace(sprite2->getPosition());
CCPoint point2 = sprite1->convertToWorldSpace(sprite2->getPosition());
CCPoint point3 = sprite1->convertToNodeSpaceAR(sprite2->getPosition());
CCPoint point4 = sprite1->convertToWorldSpaceAR(sprite2->getPosition());
CCLog("position = (%f,%f)",point1.x,point1.y);
CCLog("position = (%f,%f)",point2.x,point2.y);
CCLog("position = (%f,%f)",point3.x,point3.y);
CCLog("position = (%f,%f)",point4.x,point4.y);
运行结果:
position = (-25.000000,-60.000000)
position = (15.000000,20.000000)
position = (-25.000000,-60.000000)
position = (15.000000,20.000000)
和预算的一样

这里在将sprite1的锚点设置成(0.5,0.5),对convertToNodeSpaceAR和convertToWorldSpaceAR进行了进一步的测试
sprite1->setAnchorPoint(ccp(0.5,0.5));
sprite1->setPosition(ccp(100,100));
CCPoint point5 = sprite1->convertToNodeSpaceAR(sprite2->getPosition());
CCPoint point6 = sprite1->convertToWorldSpaceAR(sprite2->getPosition());
CCLog("position = (%f,%f)",point5.x,point5.y);
CCLog("position = (%f,%f)",point6.x,point5.y);

运算结果:
size = (40.000000,40.000000)
position = (-105.000000,-120.000000)
position = (95.000000,80.000000)
分析:重置的sprite1的坐标为(100,100),锚点为(0.5,0.5)所以对于convertToNodeSpaceAR和convertToWorldSpaceAR这两个方法的坐标系为原点(100,100),所以用convertToNodeSpaceAR转化之后的坐标为(-105,-120)用convertToWorldSpaceAR化之后的坐标为(95,80),和运算结果一样
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/yuer_xyf/article/details/45643621

智能推荐

题目:约瑟夫环_夜阑優琿的博客-程序员秘密

题解:这里的约瑟夫环是通过对数组长度的循环位移实现的,注意每次操作后数组长度减一。题中的约瑟夫环每次位移是移三位,但要注意每次位移前都要删除当前元素,所以实际上每次只要移两位就行了。题目:问题 C: 约瑟夫环时间限制: 1 Sec 内存限制: 128 MB提交: 1109 解决: 624[提交][状态][讨论版]题目描述有n个人围成一个圈,从第一个人开始顺序报号1,2,3。凡是报到3退出圈子中的人原来的序号。要求打印出退出人的序号。以及找出最后留在圈子中的人原来的序号。输入

编译原理简明综述笔记_s605133696的博客-程序员秘密_编译原理过程综述

1.1编译相关名词编译程序:源语言为“高级语言”,目标语言为“低级语言”的翻译程序宿主机:运行编译程序的计算机目标机:运行编译程序所产生目标代码的计算机从功能上分诊断编译程序(Diagnostic Compiler):专于帮助程序开发和调试的编译程序优化编译程序(Optimizing Compiler):着重于提高目标代码效率的编译程序交叉编译程序(Cr

c语言用递归方法实现冒泡排序,C语言 冒泡排序 递归法_weixin_39715834的博客-程序员秘密

1 #include 2 #include 3 int main()4 {56 void bubble(int *a,int n);78 int i,n,a[100];910 printf("请输入数组中元素数量(不大于100个):");11 scanf("%d",&n);1213 for(;n<1||n>100;){14 ...

Go 交叉编译x86, arm架构上的Linux可执行程序_叨陪鲤的博客-程序员秘密

1. Golang的交叉编译说明????????????golang中交叉编译非常简单。????????????直接在windows上设置几个Go环境变量便可以编译多种架构多个操作系统的可执行程序。https>go envset GO111MODULE=autoset GOARCH=amd64set GOBIN=set GOCACHE=C:\Users\Admin\AppData\Local\go-buildset GOENV=C:\Users\Admin\AppData\Roamin

雪花ID(Go 实现)_wang豪的博客-程序员秘密_golang 雪花id

雪花ID的实现之前做项目的时候遇到,今天再深入理解一下。文章目录雪花ID的实现前言一、雪花ID的作用?二、雪花ID的原理三、雪花ID的代码实现(Go 语言)四、雪花ID 的缺点前言雪花ID 最由推特开源的一种全局唯一ID 的生成算法,有递增、全局唯一等特性。一、雪花ID的作用?全局的唯一性对于多台机器,毫秒级生成多条不重复ID递增性生成的雪花ID具有递增型,可以加速查询。可用性高支持多线程,分布式的系统架构二、雪花ID的原理最高位是符号位,生成的ID总是正数,

OKHttp以文件形式上传图片_jianning-wu的博客-程序员秘密

AndroidOkhttp框架以文件形式上传图片以Post为例public Observable<String> postImageview(final String url, final MultipartBody requestBody){ //创建被观察者 Observable<String> observable...

随便推点

HTTPS 协议核心原理_爱好学习的青年人的博客-程序员秘密

HTTPS 协议核心原理“安全”的四个特性机密性(加解密)完整性(摘要算法)身份认证(接收方确认身份)不可抵赖(发送方不能否认自己的行为)后两个通过私钥加密,公钥解密 以及 摘要算法实现的数字签名 进行实现对称加密对称加密: 客户端和服务器共享同一个密钥,客户端给服务器发消息时,客户端用此密钥加密,服务器用此密钥解密;反过来,服务器给客户端发消息时,相反的过程。这种加密方式在互联网上有两个问题:**1. 密钥如何传输?**密钥A的传输也需要另外一个密钥B,密钥B的传

分布式数据库一定会替代Oracle吗?_dotNET跨平台的博客-程序员秘密

在传统数据库领域,Oracle一直占据了很大的市场份额,很多企业的业务系统基于此实现OLTP交易场景。近年来,随着分布式技术的发展,分布式数据库逐渐占据了OLTP领域较大的市场,尤其在互联...

使用JSON Server在项目中配置Mock数据以及json server的基本数据操作_无处不楼台的博客-程序员秘密

1、项目根目录下键入:yarn add json-server -D等待安装成功。2、在项目根目录下新建文件夹“__json_server_mock__”.这个文件夹名字前后代两个杠,代表这个文件夹实际与本项目代码关系不大。3、在此新建文件夹中创建文件“db.json”,写入:{ "user":[]}4、再在package.json中找到以下代码,并添加代码:"scripts": { "start": "react-scripts start",

r语言 与python r中python环境的创建_youngleeyoung的博客-程序员秘密

#remotes::install_github(“rstudio/reticulate”)library(reticulate)use_condaenv(‘C:/Users/yll/AppData/Local/r-miniconda/envs/giotto_env/’)‘’’conda_install(envname = “giotto_env” , packages=c(“pandas”, “python-igraph”, “networkx”, “python-louvain”, “leid

数组_学无止境0101的博客-程序员秘密

数组数组的定义数组是相同类型数据的有序集合数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成的其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问他们数组声明创建首先必须声明数组变量,才能在程序中使用数组。下面是声明数组变量的语法:dataType[] arrayRefVar; //首选的方法或dataType arrayReFVar;//效果相同但不是首选方法Java语言使用new操作符来创建数组,语法如下:dataType[] arra

在Linux下编写运行你的第一条代码——Hello Linux_Q-WHai的博客-程序员秘密

最近刚接触Linux,也是在啃那个公认的《鸟哥的Linux私房菜》。是的,的确讲得挺好的。现在看到第10章 vim程序编辑器。虽然鸟哥不太建议我们跳着来阅读他的文章,但是我还是跳了一两个章节没有阅读。别误会,我不是大牛。其实,知道vim也不是学到这一章才了解的。之前是知道的,也用过。不过想在vim中编写C代码的还就是刚刚的想法。于是,我做了一个实验。