http://www.2cto.com/kf/201402/280706.html
萌生系统了解这方面的问题这个念头, 是因为今天刚遇到的一个问题。
最近在写一个跑酷游戏,基于cocos2d-x。 在死亡判断的时候,有一个情况,就是主角被移出了屏幕可见范围,则判断为死亡。(玩过天天酷跑的都知道吧)
本来一个很简单的问题,却因为自己学习的不够系统,折腾了半天。
因为我的主角(sprite)的父类是地图(map),而不是直接加到游戏场景中(scence)。所以,我通过getPosition获得到的坐标,是相对地图的。无法直接和屏幕做比较。
于是乎,我又计算出地图相对于场景的坐标,再进行换算,得到精灵相对与场景的坐标,再判断是否在可见范围....
折腾了半天,虽然达到了要求,但是。很麻烦!
后来百度了一下.. 发现了世界坐标系这个概念。
仅仅两行代码,就解决了,而且十分准确,方便。
?12345678910 CCPoint worldSpace = getGameMap()->convertToWorldSpace(getCurrentRolePoint()); if (worldSpace.x <= 0) { //修改图片,改为受伤状态 mSprite->stopAllActions(); mSprite->setTexture(picHurt); return; }
后悔阿...
恶补了一下,mark一下。
下面就系统的介绍下cocos2d-x中的坐标系。(参考网上一些博文,加上自己的心得写成的 )
参考文章:http://blog.csdn.net/crayondeng/article/details/11936309
一、
(1)OpenGL坐标系
Cocos2D-x以OpenGL和OpenGL ES为基础,所以自然支持OpenGL坐标系。该坐标系原点在屏幕左下角,x轴向右,y轴向上。
(2)屏幕坐标系
屏幕坐标系使用的是不同的坐标系统,原点在屏幕左上角,x轴向右,y轴向下。iOS的屏幕触摸事件CCTouch传入的位置信息使用的是该坐标系。因此在Cocos2D-x中对触摸事件做出响应前,需要首先把触摸点转化到OpenGL坐标系。这一点在后面的触屏信息中会详细介绍,可以使用CCDirector的convertToGL方法来完成这一转化。
在处理触摸事件的回调方法中,我们会经常碰到这两者的坐标系统的转换处理问题。在CCTouch文件中已经为我们封装好了获取触摸点在OpenGL坐标系统和屏幕坐标系统中的坐标位置。
①从触摸点获取到在屏幕坐标系中的坐标
[cpp] view plaincopy
// returns the current touch location in screen coordinates
CCPoint CCTouch::getLocationInView() const
{
return m_point;
}
②从触摸点获取到在OpenGL坐标系中的坐标
[cpp] view plaincopy
// returns the current touch location in OpenGL coordinates
CCPoint CCTouch::getLocation() const
{
return CCDirector::sharedDirector()->convertToGL(m_point);
}
二、
(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中定义了以下四个常用的坐标变换的相关方法。
[cpp] view plaincopy
/**
* Converts a Point to node (local) space coordinates. The result is in Points.
*/
CCPoint convertToNodeSpace(const CCPoint& worldPoint);
/**
* Converts a Point to world space coordinates. The result is in Points.
*/
CCPoint convertToWorldSpace(const CCPoint& nodePoint);
/**
* Converts a Point to node (local) space coordinates. The result is in Points.
* treating the returned/received node point as anchor relative.
*/
CCPoint convertToNodeSpaceAR(const CCPoint& worldPoint);
/**
* Converts a local Point to world space coordinates.The result is in Points.
* treating the returned/received node point as anchor relative.
*/
CCPoint convertToWorldSpaceAR(const CCPoint& nodePoint);
convertToWorldSpace:把基于当前节点的本地坐标系下的坐标转换到世界坐标系中。
convertToNodeSpace:把世界坐标转换到当前节点的本地坐标系中。
这两种转换都是不考虑锚点的,都以当前节点父类的左下角的坐标为标准。另外,CCNode还提供了convertToWorldSpaceAR和convertToNodeSpaceAR。这两个方法完成同样的功能,但是它们的基准坐标是基于坐标锚点的。几乎所有的游戏引擎都会使用类似的本地坐标系而非世界坐标系来指定元素的位置。
这样做的好处是,当计算物体运动的时候,使用同一本地坐标系的元素可以作为一个子系统独立计算,最后再加上坐标系的运动即可,这是物理研究中常用的思路。例如,一个在行驶的车厢内上下跳动的人,只需要在每帧绘制的时候计算他在车厢坐标系中的位置,然后加上车的位置就可以计算出人在世界坐标系中的位置。如果使用单一的世界坐标系,人的运动轨迹就变复杂了,就涉及中学所学到的运动轨迹的合成与分解。
上面的解释也是来自Cocos2dx权威指南一书,下面我通过一个例子来说明这四个方法的理解和作用。
1、convertToNodeSpace 和 convertToWorldSpace
[cpp] view plaincopy
CCSprite *sprite1 = CCSprite::create("CloseNormal.png");
sprite1->setPosition(ccp(20,40));
sprite1->setAnchorPoint(ccp(0,0));
this->addChild(sprite1); //此时添加到的是世界坐标系,也就是OpenGL坐标系
CCSprite *sprite2 = CCSprite::create("CloseNormal.png");
sprite2->setPosition(ccp(-5,-20));
sprite2->setAnchorPoint(ccp(1,1));
this->addChild(sprite2); //此时添加到的是世界坐标系,也就是OpenGL坐标系
//将 sprite2 这个节点的坐标ccp(-5,-20) 转换为 sprite1节点 下的本地(节点)坐标系统的 位置坐标
CCPoint point1 = sprite1->convertToNodeSpace(sprite2->getPosition());
//将 sprite2 这个节点的坐标ccp(-5,-20) 转换为 sprite1节点 下的世界坐标系统的 位置坐标
CCPoint point2 = sprite1->convertToWorldSpace(sprite2->getPosition());
CCLog("position = (%f,%f)",point1.x,point1.y);
CCLog("position = (%f,%f)",point2.x,point2.y);
运行结果:
[cpp] view plaincopy
Cocos2d: position = (-25.000000,-60.000000)
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)
<喎�"http://www.2cto.com/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+CjKhomNvbnZlcnRUb05vZGVTcGFjZUFSICC6zSAgY29udmVydFRvV29ybGRTcGFjZUFSPC9wPgo8cD4K16LS4rW91eLBvbj2t723qNa7sru5/dT2vNPBy0FStcTUvMr4o6zSsry0w6q146GjxuTS4su8ysejutDeuMSx5Lu7tcS7+de8oaPV4tH5wO294qO6PC9wPgo8cD4KY29udmVydFRvTm9kZVNwYWNlQVKjrL7Nyse9q73atePX+LHqz7W1xNf4serUrbXj0N64xNTaxuTDqrXjzrvWw6Gjo6hjb252ZXJ0VG9Ob2RlU3BhY2Ugvdq149f4serPtbXE1K2148671sPKx8bk1/PPwr3Ho6k8L3A+CjxwPgpjb252ZXJ0VG9Xb3JsZFNwYWNlQVKjrL7NysfU2rHku7u1xMqxuvK9q7LO1dXX+LHq0N64xLW9xuTDqrXjzrvWw6Gjo6hjb252ZXJ0VG9Xb3JsZFNwYWNlILLO1dXX+LHqysfU2sbk1/PPwr3Ho6k8YnI+CjwvcD4KPHA+Cs/Cw+a4+LP20ru49sD919PLtcP30rvPwtXiwb249re9t6ijujwvcD4KPHA+CjwvcD4KCgoKPHN0cm9uZz5bY3BwXTwvc3Ryb25nPiB2aWV3CiBwbGFpbmNvcHkKCgoKCjxvbCBzdGFydD0="1" class="dp-cpp">
CCSprite *sprite1 = CCSprite::create("CloseNormal.png");
sprite1->setPosition(ccp(100,100));
sprite1->setAnchorPoint(ccp(0.5,0.5));
this->addChild(sprite1);
CCSprite *sprite2 = CCSprite::create("CloseNormal.png");
sprite2->setPosition(ccp(-5,-20));
sprite2->setAnchorPoint(ccp(1,1));
this->addChild(sprite2);
CCPoint point3 = sprite1->convertToNodeSpaceAR(sprite2->getPosition());
CCPoint point4 = sprite1->convertToWorldSpaceAR(sprite2->getPosition());
CCLog("position = (%f,%f)",point3.x,point3.y);
CCLog("position = (%f,%f)",point4.x,point4.y);
运行结果:
[cpp] view plaincopy
Cocos2d: position = (-105.000000,-120.000000)
Cocos2d: position = (95.000000,80.000000)
首先关于 convertToNodeSpaceAR 我们可以用下面这个图来看。
sprite1节点的节点坐标系原点现在变成节点的锚点所在位置,在这个位置建立一个坐标系,那么就可以确定sprite2转换到这个节点坐标系所在的位置了。
而关于 convertToWorldSpaceAR 其实其变换和 convertToWorldSpace 是十分类似的,只不过其原点变成其节点的锚点,而不是左下角。
那么变换的过程: sprite2变换后的坐标(90,80) = sprite1的锚点(100,100) + 平移(-5,-20)。
学习的路上,与君共勉
分享到:
相关推荐
在游戏开发中,坐标系是一个基础而重要的概念,尤其是在使用Cocos2d-x这类游戏引擎时。坐标系关系到游戏元素在屏幕上的显示位置,以及游戏逻辑中对元素位置的处理。本文将详细介绍在Cocos2d-x中使用到的三种坐标系:...
Cocos2d-x学习笔记(三)—— 坐标系
转换后的坐标会处于屏幕的左上角为原点的坐标系中,其中x和y值范围在0到1之间。如果需要将其转换为像素坐标,可以乘以屏幕的宽度和高度。但需要注意的是,Unity的屏幕y轴方向是反的,因此,屏幕坐标系统的y轴是从...
5. **坐标系**:在OpenGL ES中,坐标系原点位于屏幕底部中央,Y轴向上,X轴向右。`anchorPoint`是精灵的锚点,用于指定旋转和缩放的中心点。 6. **Menu与MenuItem**:菜单用于展示游戏的交互元素,如按钮。MenuItem...
在Cocos2D-X中,有多种坐标系用于定位和渲染元素,包括: - **OpenGL坐标系**:原点位于屏幕左下角,X轴向右,Y轴向上。 - **屏幕坐标系**:原点位于屏幕左上角,X轴向右,Y轴向下。 - **世界坐标系**:是游戏内部...
3. **关于cocoa和cocos2d的简单坐标系关系**:Cocos2d是基于Cocoa Touch构建的,因此了解Cocoa中的坐标系统对理解Cocos2d的布局至关重要。在Cocos2d中,坐标原点通常位于屏幕左上角,而Y轴向下。熟悉这个坐标系统有...
`draw()`方法允许我们在屏幕坐标系上直接绘制,因此我们可以在此处利用OpenGL ES的顶点数组和着色器来实现描边效果。通常,我们会先绘制原文字,然后在周围加上一圈与设定颜色和宽度一致的线条,以达到描边的效果。 ...
在Cocos2d-x游戏中,理解各种坐标系的概念至关重要,因为它们定义了游戏对象在屏幕上的位置和相互关系。下面我们将详细探讨世界坐标系、本地坐标系、OpenGL坐标系以及屏幕坐标系。 1. **世界坐标系 (World ...
Cocos2D-iPhone使用的是屏幕坐标系,原点位于左下角,x轴向右,y轴向上。这种坐标系与传统的直角坐标系有所不同,因此在处理位置和布局时需要注意坐标方向。Cocos2D-iPhone还提供了`CCPoint`和`CGSize`等类型,用于...
- **坐标系**:OpenGL ES使用右手坐标系,Z轴正方向朝向屏幕内部。 - **着色器**:程序片段,运行在GPU上,负责颜色计算和光照效果。 - **帧缓冲区**:用于存储最终图像的内存区域。 - **纹理**:在图像数据上...
3. **确定位置**:Cocos2d使用左下角作为坐标原点(0,0),与常见的左上角坐标系不同。若要将玩家精灵放置在屏幕左侧中央,则x坐标应为玩家精灵宽度的一半,而y坐标则为屏幕高度的一半。 #### 进阶知识点 - **动画...
当CCSprite对象转换坐标系的时候,它所包含的CCSprite对象也会转换坐标系。sprites是CCNode的子类,所以他们也可以使用actions来转换坐标。 三、CCNode CCNode是场景、层、菜单、精灵等所有节点的父类,它是一个...
- 首先,需要转换obb的坐标到矩形的局部坐标系,这样可以简化问题,使得obb看起来像是静止的。 - 然后,计算obb的边线与矩形边线的最小距离,如果所有边的距离都大于零,则说明没有碰撞;如果存在某个边的距离小于...
【cocos2d-x 自学文档】 cocos2d-x 是一个开源的游戏开发框架,它基于C++,广泛应用于移动游戏开发。以下是一些cocos2d-x的关键知识点: 一、运动中的加速度 在cocos2d-x中,我们可以利用Ease系列的方法来实现物体...
### Cocos2d-android 游戏引擎概览 #### 一、引言 Cocos2d-android是一款基于Java编写的2D游戏开发引擎,适用于Android平台。作为一个成熟且功能丰富的游戏开发工具,Cocos2d-android提供了丰富的API,使得开发者...
如果游戏包含物理引擎,如Box2D,那么屏幕方向的改变可能会影响到物理世界的坐标系。需要在屏幕切换时相应地调整物理世界的方向和比例,以保持游戏逻辑的一致性。 5. **测试与优化** 在实现横竖屏切换后,务必在...
Cocos2d-x是一款流行的开源游戏开发框架,广泛用于2D游戏的开发。在这个系列的开发笔记中,我们将深入探讨如何使用Cocos2d-x与Tiled Map Editor结合,创建和管理游戏地图。Tiled Map Editor是一款强大的2D地图编辑器...