一、

(1)OpenGL坐标系

Cocos2D-x以OpenGL和OpenGL ES为基础,所以自然支持OpenGL坐标系。该坐标系原点在屏幕左下角,x轴向右,y轴向上。

(2)屏幕坐标系

屏幕坐标系使用的是不同的坐标系统,原点在屏幕左上角,x轴向右,y轴向下。iOS的屏幕触摸事件CCTouch传入的位置信息使用的是该坐标系。因此在Cocos2D-x中对触摸事件做出响应前,需要首先把触摸点转化到OpenGL坐标系。这一点在后面的触屏信息中会详细介绍,可以使用CCDirector的convertToGL方法来完成这一转化。

在处理触摸事件的回调方法中,我们会经常碰到这两者的坐标系统的转换处理问题。在CCTouch文件中已经为我们封装好了获取触摸点在OpenGL坐标系统和屏幕坐标系统中的坐标位置。

①从触摸点获取到在屏幕坐标系中的坐标

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

②从触摸点获取到在OpenGL坐标系中的坐标

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

二、
(1)世界坐标系统

世界坐标系也叫作绝对坐标系,是游戏开发中建立的概念,因此,“世界”即是游戏世界。它建立了描述其他坐标系所需要的参考标准。我们能够用世界坐标系来描述其他坐标系的位置。它是Cocos2D-x中一个比较大的概念。

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中定义了以下四个常用的坐标变换的相关方法。

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

convertToWorldSpace:把基于当前节点的本地坐标系下的坐标转换到世界坐标系中。

convertToNodeSpace:把世界坐标转换到当前节点的本地坐标系中。

这两种转换都是不考虑锚点的,都以当前节点父类的左下角的坐标为标准。另外,CCNode还提供了convertToWorldSpaceAR和convertToNodeSpaceAR。这两个方法完成同样的功能,但是它们的基准坐标是基于坐标锚点的。几乎所有的游戏引擎都会使用类似的本地坐标系而非世界坐标系来指定元素的位置。

这样做的好处是,当计算物体运动的时候,使用同一本地坐标系的元素可以作为一个子系统独立计算,最后再加上坐标系的运动即可,这是物理研究中常用的思路。例如,一个在行驶的车厢内上下跳动的人,只需要在每帧绘制的时候计算他在车厢坐标系中的位置,然后加上车的位置就可以计算出人在世界坐标系中的位置。如果使用单一的世界坐标系,人的运动轨迹就变复杂了,就涉及中学所学到的运动轨迹的合成与分解。

上面的解释也是来自Cocos2dx权威指南一书,下面我通过一个例子来说明这四个方法的理解和作用。

1、convertToNodeSpace  和  convertToWorldSpace

  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. CCSprite *sprite2 = CCSprite::create("CloseNormal.png");
  6. sprite2->setPosition(ccp(-5,-20));
  7. sprite2->setAnchorPoint(ccp(1,1));
  8. this->addChild(sprite2); //此时添加到的是世界坐标系,也就是OpenGL坐标系
  9. //将 sprite2 这个节点的坐标ccp(-5,-20) 转换为 sprite1节点 下的本地(节点)坐标系统的 位置坐标
  10. CCPoint point1 = sprite1->convertToNodeSpace(sprite2->getPosition());
  11. //将 sprite2 这个节点的坐标ccp(-5,-20) 转换为 sprite1节点 下的世界坐标系统的 位置坐标
  12. CCPoint point2 = sprite1->convertToWorldSpace(sprite2->getPosition());
  13. CCLog("position = (%f,%f)",point1.x,point1.y);
  14. CCLog("position = (%f,%f)",point2.x,point2.y);

运行结果:

  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)

2、convertToNodeSpaceAR  和  convertToWorldSpaceAR

注意到这两个方法只不过增加了AR的约束,也即锚点。其意思是:修改变换的基准。这样理解:

convertToNodeSpaceAR,就是将节点坐标系的坐标原点修改在其锚点位置。(convertToNodeSpace 节点坐标系的原点位置是其左下角)

convertToWorldSpaceAR,就是在变换的时候将参照坐标修改到其锚点位置。(convertToWorldSpace 参照坐标是在其左下角)

下面给出一个例子说明一下这两个方法:

  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. CCSprite *sprite2 = CCSprite::create("CloseNormal.png");
  6. sprite2->setPosition(ccp(-5,-20));
  7. sprite2->setAnchorPoint(ccp(1,1));
  8. this->addChild(sprite2);
  9. CCPoint point3 = sprite1->convertToNodeSpaceAR(sprite2->getPosition());
  10. CCPoint point4 = sprite1->convertToWorldSpaceAR(sprite2->getPosition());
  11. CCLog("position = (%f,%f)",point3.x,point3.y);
  12. CCLog("position = (%f,%f)",point4.x,point4.y);

运行结果:

  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

cocos2dx中的坐标系统的更多相关文章

  1. Cocos2d-x 详解坐标系统

    这篇博文将介绍一下在cocos2dx中的一些坐标系统概念: 一. (1) OpenGL坐标系 Cocos2D-x以OpenGL和OpenGL ES为基础,所以自然支持OpenGL坐标系.该坐标系原点在 ...

  2. Cocos2d-x v3.1 坐标系统(五)

    Cocos2d-x v3.1 坐标系统(五) 为了能够更好的布局以及了解对象所在的位置,我们必须对Cocos2d-x中的坐标有详细的了解,本篇文章主要就是了解Cocos中用到的坐标系统.学过数学的人都 ...

  3. Cocos2dx中线程优先级

    Cocos2dx中线程优先级问题 不论是ios还是android,遇到耗时的任务都要另起线程处理,否则程序不能及时用户的反馈.游戏中如果一圈循环不能在1/frameRate(帧率是30则1/30)秒内 ...

  4. ArcGIS中的坐标系统定义与投影转换【转】

    ArcGIS中的坐标系统定义与投影转换 坐标系统是GIS数据重要的数学基础,用于表示地理要素.图像和观测结果的参照系统,坐标系统的定义能够保证地理数据在软件中正确的显示其位置.方向和距离,缺少坐标系统 ...

  5. 【Cocos2d-x游戏开发】Cocos2d-x中的弱联网技术

    在上一篇博客中,我们一起学习了如何在Cocos2d-x中存储数据和读取信息,本篇博客我们将一起讨论和数据存储同样重要的联网技术. 一.弱联网技术介绍 在网络游戏中许多重要的功能都需要网络连接,而根据需 ...

  6. 【Cocos2d-x游戏开发】Cocos2d-x中的数据存储技术

    一.引言 数据存储和网络功能可以说是一款游戏中必不可少的功能,如果一款游戏不能保存进度那么它的可玩性必然大打折扣(试想一下,玩家辛辛苦苦玩了一整天的游戏,结果退出时告诉人家不能保存关卡信息,你明天还得 ...

  7. cocos2dx 中使用的一些C++ 11 特性

    0.  placeholder 头文件:<functional> namespace: placeholder placeholder 就是一堆帮助bind占参数位置的东西,名字分别为 _ ...

  8. 【转】+【举例】ArcGIS中的坐标系统定义与投影转换

    背景知识: UTM (Universal Transverse Mercator)坐标系是由美国军方在1947提出的.虽然我们仍然将其看作与"高斯-克吕格"相似的坐标系统,但实际上 ...

  9. cocos2dx中CC_CALLBACK_1等宏中this指针实际指向

    首先看代码,我在Helloworld中添加两个函数. void HelloWorld::addTarget(){ Size visibleSize = Director::getInstance()- ...

随机推荐

  1. [RDLC]一步一步教你使用RDLC(一)

    一:加数据集,并且命名为Quotation,如下图所示: 二: 添加一张报表,命名为Quotation,如下图所示: 向报表中添加"表"这一项,如下图所示: 这时就弹出一个选择数据 ...

  2. (四十八)Quartz2D引擎进阶

    图形上下文栈: 应用,修改过上下文后,下一次画会在这个基础上进行,如果清空状态,需要上下文栈. 可以先把原来的上下文保存起来,然后恢复: - (void)drawRect:(CGRect)rect { ...

  3. Linux进程实践(4) --wait避免僵尸进程

    Wait的背景 当子进程退出的时候,内核会向父进程发送SIGCHLD信号,子进程的退出是个异步事件(子进程可以在父进程运行的任何时刻终止) 子进程退出时,内核将子进程置为僵尸状态,这个进程称为僵尸进程 ...

  4. Linux 学习笔记_12_文件共享服务_3_NFS网络文件服务

    NFS网络文件服务 NFS---- Network File System 用于UNIX/Linux[UNIX类操作系统]系统间通过网络进行文件共享,用户可以把网络中NFS服务器提供的共享目录挂载到本 ...

  5. json解析,异步下载(listview仅滑动时加载)Demo总结

    异步加载的练习demo 主要涉及知识点: 1.解析json格式数据,主要包括图片,文本 2.使用AsynTask异步方式从网络下载图片 3.BaseAdapter的"优雅"使用 4 ...

  6. Advanced Pricing - How to source Pricing Attributes using QP_CUSTOM_SOURCE.Get_Custom_Attribute_Valu

    详细内容需要参考文档:Oracle 11i Advanced Pricing-Don't Customize, Extend! utl:http://blog.csdn.net/cai_xingyun ...

  7. LeetCode之“动态规划”:Word Break && Word Break II

     1. Word Break 题目链接 题目要求: Given a string s and a dictionary of words dict, determine if s can be seg ...

  8. 数据包接收系列 — IP协议处理流程(二)

    本文主要内容:在接收数据包时,IP协议的处理流程. 内核版本:2.6.37 Author:zhangskd @ csdn blog 我们接着来看数据包如何发往本地的四层协议. ip_local_del ...

  9. 利用PreLoader实现一个平视显示(HUD)效果(可以运用到加载等待效果),并进行简单的讲解

    什么是PreLoader? PreLoader是由Volodymyr Kurbatov设计的一个很有意思的HUD(平视显示效果(Head Up Display)),通过运动污点和固定污点之间的粘黏动画 ...

  10. SharePoint 2013配置开发环境,需安装VS2012插件

    SharePoint 2013已经安装好了,接下来就是配置开发环境,安装VS2012,但是,装好了以后,发现没有SharePoint 2013开发的支持,如下图: 然后,去网上查找资料,VS2012对 ...