为你解说cocos2d 坐标转换一些内容

2015年03月14日 15:46 0 点赞 0 评论 更新于 2025-11-21 17:04

在Cocos2D开发中,坐标转换是一项常见且重要的操作。通常,我们会遇到以下两种坐标转换情况:

常见坐标转换场景

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

若要实现此转换,可直接使用 nodeParent->convertToWorldSpace(node->getPosition())。需要注意的是,这里必须由需要转换坐标对象的父类调用 convertToWorldSpace 方法,其参数为对象相对于父类的坐标点,该方法返回的是屏幕坐标点。

2. 从当前坐标点获取相对于某个 CCNode 的坐标点

这种情况下,可使用 node2->convertToNodeSpace(node1->getPosition())。这里的 node2 不一定是 node1 的父类,此操作的目的是让 node1 得到相对于 node2 坐标系的坐标点,返回的就是相对于 node2 坐标系的坐标点。

上述调用默认使用的是 (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))

四个坐标转换方法研究

Cocos2D - X 中有四个表示坐标的方法,下面我们来详细研究一下:

CCPoint convertToNodeSpace(const CCPoint& worldPoint);
CCPoint convertToWorldSpace(const CCPoint& nodePoint);
CCPoint convertToNodeSpaceAR(const CCPoint& worldPoint);
CCPoint convertToWorldSpaceAR(const CCPoint& nodePoint);

在理解这些方法之前,我们需要对世界坐标和本地坐标有一定的认识。

坐标系介绍

1. GL坐标系

Cocos2D以OpenGL ES为图形库,因此使用OpenGL ES坐标系。该坐标系的原点位于屏幕左下角,x轴向右,y轴向上。

2. 屏幕坐标系

苹果的Quartz2D使用的是不同的坐标系统,其原点在屏幕左上角,x轴向右,y轴向下。iOS的屏幕触摸事件 CCTouch 传入的位置信息使用的就是该坐标系。所以在Cocos2D中对触摸事件做出响应前,需要先把触摸点转化到GL坐标系,可使用 CCDirectorconvertToGL 方法完成这一转化。

3. 世界坐标系

也称为绝对坐标系。在Cocos2D中,元素具有父子关系的层级结构。我们通过 CCNodeposition 设定元素的位置时,使用的是相对其父节点的本地坐标系,而非世界坐标系。在绘制屏幕时,Cocos2D会把这些元素的本地坐标映射成世界坐标系坐标。世界坐标系和GL坐标系一致,原点在屏幕左下角。

4. 本地坐标系

本地坐标系也叫物体坐标系,是和特定物体相关联的坐标系。每个物体都有独立的坐标系,当物体移动或改变方向时,与之关联的坐标系也会随之移动或改变方向。例如,用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 的本地坐标。

2. convertToWorldSpace

调用方式为 CCPoint point = node1->convertToWorldSpace(node2->getPosition());,此方法是将 node2 的坐标转化成相对于 node1 的世界坐标。具体操作是先将 node1 的坐标当做世界坐标,然后让 node2 的坐标位置重置成相对于 node1 的世界坐标。

3. convertToNodeSpaceAR

该方法是把 node1 的坐标系原点设置在锚点的位置。若锚点为 (0, 0),则转化之后的坐标系位置和 convertToNodeSpace 一样,结果也相同。

4. convertToWorldSpaceAR

convertToNodeSpaceAR 同理。

测试代码及结果分析

第一次测试

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的坐标转换有了更深入的理解,在实际开发中就能更准确地运用这些方法进行坐标转换。

作者信息

feifeila

feifeila

共发布了 3994 篇文章