Cocos2d-x 3.0坐标系详解(转载)

Cocos2d-x
3.0坐标系详解

Cocos2d-x坐标系和OpenGL坐标系相同,都是起源于笛卡尔坐标系。

笛卡尔坐标系

笛卡尔坐标系中定义右手系原点在左下角,x向右,y向上,z向外,OpenGL坐标系为笛卡尔右手系。



屏幕坐标系和Cocos2d坐标系

标准屏幕坐标系使用和OpenGL不同的坐标系,而Cocos2d则使用和OpenGL相同的坐标系。

iOS,
Android, Windows
Phone等在开发应用时使用的是标准屏幕坐标系,原点为屏幕左上角,x向右,y向下。

Cocos2d坐标系和OpenGL坐标系一样,原点为屏幕左下角,x向右,y向下。

 

在开发中,我们经常会提到两个比较抽象的概念-世界坐标系和本地坐标系。这两个概念可以帮助我们更好的理解节点在Cocos2d坐标系中的位置以及对应关系。

世界坐标系(World Coordinate) VS 本地坐标系(Node
Local)

世界坐标系也叫做绝对坐标系,是游戏开发中建立的概念。因此,“世界”指游戏世界。cocos2d中的元素是有父子关系的层级结构,我们通过Node的setPosition设定元素的位置使用的是相对与其父节点的本地坐标系而非世界坐标系。最后在绘制屏幕的时候cocos2d会把这些元素的本地坐标映射成世界坐标系坐标。

本地坐标系也叫相对坐标系,是和节点相关联的坐标系。每个节点都有独立的坐标系,当节点移动或改变方向时,和该节点关联的坐标系将随之移动或改变方向。

锚点(Anchor
Point)

将一个节点添加到父节点里面时,需要设置其在父节点上的位置,本质上是设置节点的锚点在父节点坐标系上的位置。

-
Anchor Point的两个参数都在0~1之间。它们表示的并不是像素点,而是乘数因子。(0.5,0.5)表示Anchor
Point位于节点长度乘0.5和宽度乘0.5的地方,即节点的中心

-
在Cocos2d-x中Layer的Anchor Point为默认值(0,0),其他Node的默认值为(0.5,
0.5)。

我们用以下代码为例,使用默认Anchor
Point值,将红色层放在屏幕左下角,绿色层添加到红色层上:

1 auto red = LayerColor::create(Color4B(255, 100, 100, 128), visibleSize.width/2, visibleSize.height/2);
2 auto green = LayerColor::create(Color4B(100, 255, 100, 128), visibleSize.width/4, visibleSize.height/4);
3 red->addChild(green);
4 this->addChild(red, 0);


我们用以下代码为例,将红色层的Anchor
Point设为中点放在屏幕中央,绿色层添加到红色层上,绿色层锚点为右上角:

因为Layer比较特殊,它默认忽略锚点,所以要调用`ignoreAnchorPointForPosition()`接口来改变锚点,关于ignoreAnchorPointForPosition()接口的使用说明,我们将在后面详细讲解。

忽略锚点(Ignore Anchor
Point)

Ignore Anchor
Point全称是ignoreAnchorPointForPosition,作用是将锚点固定在一个地方。

如果设置其值为true,则图片资源的Anchor
Pont固定为左下角,否则即为所设置的位置。

我们用以下代码为例,将两个层的ignoreAnchorPointForPosition设为true,并将绿色的层添加到红色的层上:




复制代码

  1. auto red = LayerColor::create(Color4B(255, 100, 100, 128),
    visibleSize.width/2, visibleSize.height/2);

  2. red->ignoreAnchorPointForPosition(true);

  3. red->setPosition(Point(visibleSize.width/2 + origin.x,
    visibleSize.height/2 + origin.y));
  4. auto green = LayerColor::create(Color4B(100, 255, 100, 128),
    visibleSize.width/4, visibleSize.height/4);

  5. green->ignoreAnchorPointForPosition(true);
  6. red->addChild(green);
  7. this->addChild(red, 0);


 

VertexZ,PositionZ和zOrder

-
VertextZ是OpenGL坐标系中的Z值
-
PositionZ是Cocos2d-x坐标系中Z值
-
zOrder是Cocos2d-x本地坐标系中Z值

在实际开发中我们只需关注zOrder。

可以通过`setPositionZ`接口来设置PositionZ。

以下是`setPositionZ`接口的说明:




复制代码

  1. Sets the ‘z‘ coordinate in the position. It is the OpenGL Z vertex
    value.

即PositionZ的值即为opengl的z值VertexZ。同样节点的PositionZ也是决定了该节点的渲染顺序,值越大,但是与zOrder不同的区别在于,PositionZ是全局渲染顺序即在根节点上的渲染顺序,而zOrder则是局部渲染顺序,即该节点在其父节点上的渲染顺序,与Node的层级有关。用以下事例来说明:




复制代码

  1. auto red = LayerColor::create(Color4B(255, 100, 100, 255),
    visibleSize.width/2, visibleSize.height/2);

  2. red->ignoreAnchorPointForPosition(false); red->setPosition(Point(visibleSize.width
    / 2, visibleSize.height / 2));
  3. auto green = LayerColor::create(Color4B(100, 255, 100, 255),
    visibleSize.width/4, visibleSize.height/4);

  4. green->ignoreAnchorPointForPosition(false);

  5. green->setPosition(Point(visibleSize.width / 2,
    visibleSize.height / 2 - 100));

  6. red->setPositionZ(1);

  7. green->setPositionZ(0);

  8. this->addChild(red, 0);

  9. this->addChild(green, 1);


 

虽然green的zOrder大于red的zOder,但是因为red的PositionZ较大,所以red还是在green上面显示。

触摸点(Touch
position)

所以在处理触摸事件时需要用重写以下四个函数:




复制代码

  1. virtual bool onTouchBegan(Touch *touch, Event * event);

  2. virtual void onTouchEnded(Touch *touch, Event * event);

  3. virtual void onTouchCancelled(Touch *touch, Event *
    event);

  4. virtual void onTouchMoved(Touch *touch, Event *
    event);

在函数中获取到touch,我们在设计游戏逻辑时需要用到触摸点在Cocos2d坐标系中的位置,就需要将touch的坐标转换成OpenGL坐标系中的点坐标。

Touch
position是屏幕坐标系中的点,OpenGL
position是cocos2d-x用到的OpenGL坐标系上的点坐标。通常我们在开发中会使用两个接口`getLocation()`和`getLocationInView()`来进行相应坐标转换工作。

在开发中一般使用`getLocation()`获取触摸点的GL坐标,而`getLocation()`内部实现是通过调用`Director::getInstance()->convertToGL(_point);`返回GL坐标。

此外,关于世界坐标系和本地坐标系的相互转换,在Node中定义了以下四个常用的坐标变换的相关方法。




复制代码

  1. // 把基于当前节点的本地坐标系下的坐标转换到世界坐标系中

  2. Point convertToNodeSpace(const Point& worldPoint)
    const;
  3. // 把世界坐标转换到当前节点的本地坐标系中

  4. Point convertToWorldSpace(const Point& nodePoint)
    const;
  5. // 基于Anchor Point把基于当前节点的本地坐标系下的坐标转换到世界坐标系中

  6. Point convertToNodeSpaceAR(const Point& worldPoint)
    const;
  7. // 基于Anchor Point把世界坐标转换到当前节点的本地坐标系中

  8. Point convertToWorldSpaceAR(const Point& nodePoint)
    const;


下面通过一个例子来说明这四个方法的理解和作用:




复制代码

  1. auto *sprite1 = Sprite::create("HelloWorld.png");

  2. sprite1->setPosition(ccp(20,40));

  3. sprite1->setAnchorPoint(ccp(0,0));

  4. this->addChild(sprite1);
     //此时添加到的是世界坐标系,也就是OpenGL坐标系
  5. auto *sprite2 = Sprite::create("HelloWorld.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. Point point1 =
    sprite1->convertToNodeSpace(sprite2->getPosition());
  11. //将 sprite2 这个节点的坐标ccp(-5,-20) 转换为 sprite1节点 下的世界坐标系统的
    位置坐标

  12. Point point2 =
    sprite1->convertToWorldSpace(sprite2->getPosition());
  13. log("position = (%f,%f)",point1.x,point1.y);

  14. log("position =
    (%f,%f)",point2.x,point2.y);




复制代码

  1. 运行结果:
  2. Cocos2d: position = (-25.000000,-60.000000)

  3. Cocos2d: position =
    (15.000000,20.000000)


 

 

其中:`Point
point1 =
sprite1->convertToNodeSpace(sprite2->getPosition());` 

相当于`sprite2`这个节点添加到(实际没有添加,只是这样理解)`sprite1`这个节点上,那么就需要使用`sprite1`这个节点的节点坐标系统,这个节点的节点坐标系统的原点在(20,40),而`sprite1`的坐标是(-5,-20),那么经过变换之后,`sprite1`的坐标就是(-25,-60)。

其中:`Point
point2 =
sprite1->convertToWorldSpace(sprite2->getPosition());`

此时的变换是将`sprite2`的坐标转换到`sprite1`的世界坐标系下,而其中世界坐标系是没有变化的,始终都是和OpenGL等同,只不过`sprite2`在变换的时候将`sprite1`作为了”参照“而已。所以变换之后`sprite2`的坐标为:(15,20)。

原帖地址:http://www.cocoachina.com/bbs/read.php?tid=198283

Cocos2d-x 3.0坐标系详解(转载),布布扣,bubuko.com

时间: 2024-10-14 07:11:45

Cocos2d-x 3.0坐标系详解(转载)的相关文章

Cocos2d-x 3.0坐标系详解

Cocos2d-x坐标系和OpenGL坐标系相同,都是起源于笛卡尔坐标系. 笛卡尔坐标系 笛卡尔坐标系中定义右手系原点在左下角,x向右,y向上,z向外,OpenGL坐标系为笛卡尔右手系. 屏幕坐标系和Cocos2d坐标系 标准屏幕坐标系使用和OpenGL不同的坐标系,而Cocos2d则使用和OpenGL相同的坐标系. iOS, Android, Windows Phone等在开发应用时使用的是标准屏幕坐标系,原点为屏幕左上角,x向右,y向下. Cocos2d坐标系和OpenGL坐标系一样,原点为

ocos2d-x 3.0坐标系详解--透彻篇 ---- convertToWorldSpace:把基于当前节点的本地坐标系下的坐标转换到世界坐标系中。

convertToWorldSpace:把基于当前节点的本地坐标系下的坐标转换到世界坐标系中.重点说明:基于...   不一定要是真实的,  convertToWorldSpace 的结果也只是一个新的位置, 这个位置一般都没有什么实际意义的,大部分都是用在碰撞检测 ,一个虚拟的新位置(主要用在子弹和敌人不在同一层的情况,把子弹和敌人转换到同一节点下的本地坐标系进行位置比较,方便进行碰撞检测) 为什么官方文档,在这个文档描叙的时候,写的是基于当前节点下的坐标系....   中文还是值得深入的推敲

[转载]AxureRP 7.0部件详解(一)

本文为Axure RT7.0教程,本章主要介绍menu菜单.table表格.Tree Widget 树部件三个部件,后续将持续更新...... Menu 菜单 常用案例 网站导航菜单部件通常用于母板之中,其目的是在原型中跳转到不同页面. 编辑菜单要编辑菜单,右键点击在弹出的上下文菜单中选择 在之前/之后新增菜单项.删除菜单.新增子菜单. 菜单样式使用工具栏或部件样式面板可以编辑菜单样式,如填充颜色,字体颜色,字体大小等,需要注意的是子菜单是通过父菜单获取格式的.要自定义菜单样式,参见 弹出菜单案

CentOS 7上安装Zabbix Server 3.0 图文详解

转载自 http://www.linuxidc.com/Linux/2016-09/135204.htm CentOS 7上安装Zabbix Server 3.0 图文详解 1.查看系统信息. cat /etc/RedHat-releaseCentOS Linux release 7.0.1406 (Core) uname -a Linux VM_96_155_centos3.10.0-123.el7.x86_64 #1 SMP Mon Jun 30 12:09:22 UTC 2014 x86_

GridView内容详解(转载)

GridView内容详解(转载) GridView是ASP.NET界面开发中的一个重要的控件,对GridView使用的熟练程度直接影响软件开发的进度及功能的实现.(车延禄)GridView的主要新特性:    1.与DataSource控件结合实现了显示与数据操作的分离,大大减化了代码的编写量;    2.实现"双向绑定",无需手动检索数据.    2.在列的类型上新增了CheckBoxField和ImageField两个类型列;    3.对排序和分页可以实现异步操作;    4.对

MySQL 数据类型 详解 (转载)

数值类型 MySQL 的数值数据类型可以大致划分为两个类别,一个是整数,另一个是浮点数或小数.许多不同的子类型对这些类别中的每一个都是可用的,每个子类型支持不同大小的数据,并且 MySQL 允许我们指定数值字段中的值是否有正负之分或者用零填补. 表列出了各种数值类型以及它们的允许范围和占用的内存空间. 类型 大小 范围(有符号) 范围(无符号) 用途 TINYINT 1 字节 (-128,127) (0,255) 小整数值 SMALLINT 2 字节 (-32 768,32 767) (0,65

HTML中META属性详解 转载自 hero_213的博客

HTML中META属性详解 meta是html语言head区的一个辅助性标签.几乎所有的网页里,我们可以看到类似下面这段的html代码: <head> <meta   http-equiv= "content-Type "   content= "text/html;   charset=gb2312 "> </head>         也许你认为这些代码可有可无.其实如果你能够用好meta标签,会给你带来意想不到的效果,例如加

Python安装、配置图文详解(转载)

Python安装.配置图文详解 目录: 一. Python简介 二. 安装python 1. 在windows下安装 2. 在Linux下安装 三. 在windows下配置python集成开发环境(IDE) 1. 在Eclipse中安装PyDev插件 2. 配置Python Interpreters 四. 创建Python Project 五. 编写HelloWorld 六. 小结 一. Python简介: Python在Linux.windows.Mac os等操作系统下都有相应的版本,不管在

Retrofit2.0使用详解

Retrofit2.0使用 随笔 生活是一面镜子,不去擦拭,岁月的灰尘将掩埋它. 转载请标明出处:http://blog.csdn.net/qq_15807167/article/details/51712048 主页 Retrofit20使用 初次了解Retrofit 具体的使用文档 请求体Request Body FORM ENCODED AND MULTIPART 表单和Multipart 异步 VS 同步 Retrofit20的新知识点 Retrofit20的使用方式 使用 注意 如果有