cocos2dx的 坐标转换简单总结

2015年01月29日 10:02 0 点赞 0 评论 更新于 2025-11-21 15:41

在不同的应用场景中,Cocos2d-x 的坐标可能需要进行转换。本文将对 Cocos2d-x 的坐标转换进行简单总结。

一、Cocos2d-x 所遵循的坐标系

Cocos2d-x 基于 OpenGL ES 构建,因此遵循 OpenGL 的坐标系,该坐标系以屏幕的左下角为坐标原点,x 轴向右,y 轴向上。而屏幕坐标系(如苹果的 Quartz2D 使用)原点在屏幕左上角,x 轴向右,y 轴向下,iOS 的屏幕触摸事件 CCTouch 传入的位置信息使用的就是该坐标系。所以在 Cocos2d 中对触摸事件做出响应前,需要先把触摸点转化到 OpenGL 坐标系,可使用 CCDirectorconvertToGL 来完成这一转化。

二、坐标转换的常见情况及方法

(一)从当前坐标点获取世界坐标点(屏幕坐标点,OpenGL 的坐标系)

直接使用 nodeParent->convertToWorldSpace(node->getPosition()); 这里需要转换坐标对象的父类调用 convertToWorldSpace,参数是对象相对于父类的坐标点,返回的是屏幕坐标点。

(二)从当前坐标点获取相对于某个 CCNode 的坐标点

直接使用 node2->convertToNodeSpace(node1->getPosition()); 这里 node2 不一定是 node1 的父类,此方法可让 node1 得到相对于 node2 坐标系的坐标点,返回的就是相对于 node2 坐标系的坐标点。

(三)考虑锚点的情况

上述调用未考虑 nodeParentnode2anchorPoint(默认使用了 (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))

三、四个坐标转换方法详解

(一)相关概念

在理解 CCPoint convertToNodeSpace(const CCPoint& worldPoint);CCPoint convertToWorldSpace(const CCPoint& nodePoint);CCPoint convertToNodeSpaceAR(const CCPoint& worldPoint);CCPoint convertToWorldSpaceAR(const CCPoint& nodePoint); 这四个方法之前,需要对世界坐标和本地坐标有一定的理解。

  • 世界坐标系:也叫做绝对坐标系,Cocos2d 中的元素具有父子关系的层级结构,我们通过 CCNodeposition 设定元素的位置使用的是相对其父节点的本地坐标系,而非世界坐标系。在绘制屏幕时,Cocos2d 会把这些元素的本地坐标映射成世界坐标系坐标。世界坐标系和 OpenGL 坐标系一致,原点在屏幕左下角。
  • 本地坐标系:也叫做物体坐标系,是和特定物体相关联的坐标系。每个物体都有独立的坐标系,当物体移动或改变方向时,和该物体关联的坐标系将随之移动或改变方向。例如,用 Cocos2d-x 创建一个矩形 colorLayer: CCRect(10, 10, 100, 100),此时的本地坐标系以 (10, 10) 为坐标原点,x 轴向右,y 轴向上。若创建一个 CCSprite,锚点为 (0.5, 0.5),位置为 (100, 100),大小为 (40, 40),这时的本地坐标系以 (80, 80) 为坐标原点,x 轴向右,y 轴向上。总体而言,本地坐标系原点为 node 的左下角坐标。

(二)方法具体解析

  1. convertToNodeSpace:调用 CCPoint point = node1->convertToNodeSpace(node2->getPosition()); 可将 node2 的坐标转化成相对于 node1 的本地坐标。例如,若 node1 的锚点为 (0, 0),node2 的锚点为 (1, 1),转化之后,node2 的坐标可能变成 (-25, -60)。
  2. convertToWorldSpace:调用 CCPoint point = node1->convertToWorldSpace(node2->getPosition()); 是将 node2 的坐标转化成相对于 node1 的世界坐标。具体操作是先将 node1 的坐标当做世界坐标,然后让 node2 的坐标位置重置成相对于 node1 的世界坐标,例如可能得到 (15, 20)。
  3. convertToNodeSpaceAR:该方法是把 node1 的坐标系原点设置在锚点的位置。若锚点是 (0, 0),则转化之后的坐标系位置和 convertToNodeSpace 一样,结果也相同。
  4. convertToWorldSpaceAR:原理与 convertToNodeSpaceAR 类似,若锚点为 (0, 0),其转化结果和 convertToWorldSpace 相同。

四、测试代码及结果分析

(一)第一次测试

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->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),对于 convertToNodeSpaceARconvertToWorldSpaceAR 这两个方法,其坐标系原点为 (100, 100)。所以用 convertToNodeSpaceAR 转化之后的坐标为 (-105, -120),用 convertToWorldSpaceAR 转化之后的坐标为 (95, 80),与运算结果一致。

综上所述,通过对上述坐标转换方法的理解和测试,我们可以在 Cocos2d-x 开发中灵活运用坐标转换,以满足不同的开发需求。

作者信息

feifeila

feifeila

共发布了 3994 篇文章