cocos2d-x:OpenGL坐标系、绝对坐标系、相对坐标系、屏幕坐标系

cocos2d-x采用的是笛卡尔平面坐标系,也就是平面上两条垂直线构成的坐标系,平面上任意一点都可以用(x,y)来表示。

(1)就坐标系方向而言,cocos2d-x分为屏幕坐标系和OpenGL坐标系。

(2)就节点本身而言,cocos2d-x分为绝对坐标系和相对坐标系。

1.屏幕坐标系

屏幕坐标系,也叫UIKit坐标系,原点在屏幕左上,x轴向右,y轴向下。cocos2d-x的屏幕触摸事件传入的位置坐标就是采用了屏幕坐标系。以320*480的屏幕为例,如图坐标值为屏幕坐标系:

注:纹理坐标原点也是在左上.

2.OpenGL标系

OpenGL坐标系,原点在屏幕的左下,x轴向右,y轴向上。cocos2d-x的元素采用的就是OpenGL坐标系。同样的上例,如图坐标值为OpenGL坐标系:

3.屏幕坐标系和OpenGL坐标系的转换

它们的转换导演类(CCDirector)已经封装好了两个函数供我们使用。

//UIKit To OpenGL
CCPoint convertToGL(const CCPoint& obPoint);
//OpenGL To UIKit
CCPoint convertToUI(const CCPoint& obPoint);

注: 在调用任何需要设置位置的函数或从函数获取位置信息前,必须要明确这个函数使用的是哪个坐标系,如调用CCNode类的setPosition函数,它使用的就是GL坐标系,而在处理触摸时间时CCTouch对象在宏的坐标就是屏幕坐标。

4.绝对坐标系(世界坐标系)

绝对坐标系也叫世界坐标系(左下),从名字可以看来,绝对坐标系是一个恒坐标系,不参考也不依赖于其他坐标系。在cocos2d-x中它使用的是OpenGL坐标系。不过因为我们多在CCLayer上放置游戏元素,所以一般比较少直接用到绝对坐标系。

5.相对坐标系(节点/本地 坐标系)

cocos2d-x元素是有层次关系的,节点使用的是相对父节点的位置坐标,也就是相对坐标系(也叫本地坐标系,节点坐标),屏幕绘制的时候,cocos2d-x会自动将相对坐标系转换为绝对坐标系,渲染到屏幕的绝对位置上。

6.锚点 : 锚点是对节点而言的,它是节点的一个属性,表明了节点位置的一个参考基准点

在举例之前有必要先了解一下锚点这个概念。锚点是对节点而言的,它是节点的一个属性,表明了节点位置的一个参考基准点,同样放置一个物体在(300,300)这个位置,不同的锚点会产生不同的效果。节点的默认锚点位置在(0.5,0.5)。锚点和节点的位置值没有关系,锚点只是影响了节点在屏幕上渲染的位置。如下图,虽然精灵的在屏幕上渲染的位置不一样,但是它们的position值是一样的,都是(300,300)。锚点只会影响它本身在父节点中的渲染位置,而不会影响其子节点相对它本身的位置。

7.绝对坐标系和相对坐标系的关系

我们先看一个例子,为了方便演示,节点的锚点都设置为(0,0)。

CCSprite* big=CCSprite::create("big.png");
big->setAnchorPoint(ccp(,));
big->setPosition(ccp(,));//设置在相对父节点的(50,50)位置
this->addChild(big);//屏幕是父节点
CCSprite* little=CCSprite::create("little.png");
little->setAnchorPoint(ccp(,));
little->setPosition(ccp(,));//设置在相对父节点的(50,50)位置
big->addChild(little);//big是父节点

效果如下:

8.绝对坐标系和相对坐标系的转换

CCNode提供给我们相对坐标系和绝对坐标系的转换函数。

CCPoint convertToNodeSpace(const CCPoint& worldPoint);  //将世界坐标转换为对象节点内坐标,忽略锚点,以当前父节点左下角坐标为标准
CCPoint convertToWorldSpace(const CCPoint& nodePoint); //将对象节点内坐标转换为事件坐标,忽略锚点,以当前父节点左下角坐标为标准
CCPoint convertToNodeSpaceAR(const CCPoint& worldPoint);//将世界坐标转换为基于锚点的对象节点内坐标
CCPoint convertToWorldSpaceAR(const CCPoint& nodePoint);//将局域锚点的对象节点内坐标转换为世界坐标

如果要获取big和little的绝对坐标

CCPoint wp1=this->convertToWorldSpace(big->getPosition());//wp1(50,50)
CCPoint wp2=big->convertToWorldSpace(little->getPosition());//wp2(100,100)

如果要把绝对坐标转换为big和little的相对坐标

//世界坐标点a(200, 200)在相对big节点的位置坐标,也即在big节点中a的相对坐标为(150, 150)
CCPoint np1=big->convertToNodeSpace(ccp(,));//np1(150,150)
CCPoint np2=little->convertToNodeSpace(ccp(,));//np2(100,100)

支持以下几种坐标系:
1.屏幕坐标系 原点在左上角,X轴向右,Y轴向下。
2.GL坐标系 原点在左下角,X轴向右,Y轴向上。
3.世界坐标系 指相对于整个屏幕的坐标系,(0,0)就是屏幕的左下角,(320,480)就是屏幕的右上角。
4.本地坐标系 相对于父对象的坐标。

  另一个关键的问题就是在cocos2d里面就是各种对象的大小问题。因为在cocos2d里CCNode对象有缩放的方法setScaleX和setScaleY。所以在获取对象大小的时候就必须根据情况明确指定获取对象原始大小,还是缩放后的大小。当然cocos2d里提供了对应的函数来完成这些操作。
getContentSize 函数用来获得节点原始的大小。
boundingBox 函数用来获得经过缩放和旋转之后的外框盒大小。
举个简单的例子:

bool ret = CCRect::CCRectContainsPoint(this->boundingBox() , this->getParent()->convertTouchToNodeSpace(pTouch));

这个例子的功能是来判定当前的触摸操作是否发生在自己的node对象上。其中pTouch是CCTouch对象的指针,包含了当前触摸事件发生点的坐标。
CCRectContainsPoint这个函数用来判断一个点是否在一个矩形范围内。我们就想用这个函数来判断当前触摸操作的这个点是否在当前node的范围内。
this->boundingBox() 方法获得了当前节点对象在父节点对象下的缩放之后的本地坐标大小,并且是用GL坐标系表示的。

  pTouch对象中的坐标是屏幕坐标系,所以必须转换到GL坐标系,再转换到父节点的本地坐标下(因为是要判断是否在节点里面,所以需要转化成本地坐标,如果仅仅是屏幕点击事件,只需要转换成GL坐标)。好在convertTouchToNodeSpace这个函数一次完成了这两个转换,可以参考该库的源码,其中有具体的计算过程。所有数据都转换到同一个坐标系下了以后,就可以通过CCRectContainsPoint函数完成最终的判定操作。最后想说的一点是,尽可能用相对坐标。换句话说,程序中所有对象在设置大小和位置时,都应该以父对象的大小和位置为依据。 这样程序发布在以各种不同的分辨率发布时,只需要调整根对象的大小就可以了。

cocos2d-x游戏引擎核心之一——坐标系的更多相关文章

  1. cocos2d-x游戏引擎核心(3.x)----事件分发机制之事件从(android,ios,desktop)系统传到cocos2dx的过程浅析

    (一) Android平台下: cocos2dx 版本3.2,先导入一个android工程,然后看下AndroidManifest.xml <application android:label= ...

  2. cocos2d-x游戏引擎核心之六——绘图原理和绘图技巧

    一.OpenGL基础 游戏引擎是对底层绘图接口的包装,Cocos2d-x 也一样,它是对不同平台下 OpenGL 的包装.OpenGL 全称为 Open Graphics Library,是一个开放的 ...

  3. cocos2d-x游戏引擎核心之十一——并发编程(消息通知中心)

    [续] cocos2d-x游戏引擎核心之八——多线程 这里介绍cocos2d-x的一种消息/数据传递方式,内置的观察者模式,也称消息通知中心,CCNotificationCenter. 虽然引擎没有为 ...

  4. cocos2d-x游戏引擎核心之八——多线程

    一.多线程原理 (1)单线程的尴尬 重新回顾下 Cocos2d-x 的并行机制.引擎内部实现了一个庞大的主循环,在每帧之间更新各个精灵的状态.执行动作.调用定时函数等,这些操作之间可以保证严格独立,互 ...

  5. cocos2d-x游戏引擎核心(3.x)----启动渲染流程

    (1) 首先,这里以win32平台下为例子.win32下游戏的启动都是从win32目录下main文件开始的,即是游戏的入口函数,如下: #include "main.h" #inc ...

  6. cocos2d-x游戏引擎核心之九——跨平台

    一.cocos2d-x跨平台 cocos2d-x到底是怎样实现跨平台的呢?这里以Win32和Android为例. 1. 跨平台项目目录结构 先看一下一个项目创建后的目录结构吧!这还是以HelloCpp ...

  7. cocos2d-x游戏引擎核心之七——数据持久化

    一.XML与JSON XML 和 JSON 都是当下流行的数据存储格式,它们的共同特点就是数据明文,十分易于阅读.XML 源自于 SGML,是一种标记性数据描述语言,而 JSON 则是一种轻量级数据交 ...

  8. cocos2d-x游戏引擎核心之四——动作调度机制

    一.动作机制的用法 在深入学习动作机制在 Cocos2d-x 里是如何实现的之前,我们先来学习整套动作机制的用法,先知道怎么用,再深入学习它如何实现,是一个很好很重要的学习方法. (1)基本概念 CC ...

  9. cocos2d-x游戏引擎核心之十二——3.x新特性

    v3.0 亮点 使用 C++(C++11) 的特性取代了 Objective-C 的特性 优化了 Labels 优化了渲染器(比 v2.2 更快) 新的事件分发机制 物理引擎集成 新的 UI 对象 J ...

随机推荐

  1. javascript 中 IE与FF的不同之处及其兼容写法

    png透明 AlphaImageLoaderfilter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=bEnabled,siz ...

  2. Java中 堆 栈,常量池等概念解析(转载)

    1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制. 2. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符 ...

  3. C#递归累计到父行

    搞了半天 写了一个算法,希望能帮到需要的朋友 效果如下 水电费用是由 就是部门水费和电费累加的,而部门水费由科室水费累加起来的 表结构 DataTable dt = new DataTable(); ...

  4. Elasticsearch5.X IN Windows 10 系列文章(5)

    ElasticSearch版本: 5.5.1 (最新稳定版为5.5.2),由于用到IK中文分词插件,最新版本没有5.5.2 ,所以使用5.5.1 日期:2017-08-31 第五章:Kibana 安装 ...

  5. DataGridView使用技巧三:不显示最下面的新行、判断新增行

    一.DataGridView不显示下面的新行 通常DataGridView的最下面一行是用户新追加的行(行头显示*).如果不想让用户新追加行即不想显示该新行,可以将DataGridView对象的All ...

  6. scp基本使用方法

    scp基本使用方法: scp用于在两台电脑之间进行数据的copy,形式如下:  第一种, scp [-r] 文件/文件夹  user@host:dir ,需要输入密码.  第二种, scp [-r] ...

  7. pymongo创建索引、更新、删除

    pymongo创建索引.更新.删除     索引创建 ## collection 为数据集合collection.create_Index({'需创建索引字段': 1})collection.ensu ...

  8. 专题实验 EXP & IMP

    导入导出时 oracle 提供的实用工具, 如果这些被导出的对象还存在其他的相关对象, 比如要被导出的表上还存在索引, 注释等, 则导出工具会自动将这些相关的对象也提取出来, 并放入到导出的文件中去. ...

  9. 15 +免费及收费的jQuery滚动插件

    免费的 jQuery Scrolling 插件 Tiny Scrollbar SUPERSCROLLORAMA jScrollPane Curtain.js Plugin JQuery : Scrol ...

  10. dhcpcd 移植

    /************************************************************************ * dhcpcd移植 * dhcpcd是DHCP c ...