[cocos2dx]坐标转换

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ouyangshima/article/details/82984362

在Cocos2d-x中提供了以下的API用来进行坐标转换。

/**
* 将世界坐标转换成节点坐标,忽略锚点的影响;结果是以点为单位。
*/
Vec2 convertToNodeSpace(const Vec2& worldPoint) const;

/**
* 将节点坐标转换成世界坐标,忽略锚点的影响;结果是以点为单位。
*/
Vec2 convertToWorldSpace(const Vec2& nodePoint) const;

/**
* 将世界坐标转换成节点坐标;结果是以点为单位。
* 会考虑到锚点的影响
*/
Vec2 convertToNodeSpaceAR(const Vec2& worldPoint) const;

/**
* 将节点坐标转换成世界坐标;结果是以点为单位。
* 会考虑到锚点的影响。
*/
Vec2 convertToWorldSpaceAR(const Vec2& nodePoint) const;

/**
* 将Touch对应的点转换成节点坐标,忽略锚点的影响。
*/
Vec2 convertTouchToNodeSpace(Touch * touch) const;

/**
* 将Touch对应的点转换成节点坐标,考虑锚点的影响。
*/
Vec2 convertTouchToNodeSpaceAR(Touch * touch) const;

世界坐标系转节点坐标系,节点坐标系转世界坐标系,就这么几个函数就能搞定了,剩下的就是实际的应用了。对了,在实际中,一定要考虑到锚点的影响,可能你得到的结果,就是因为锚点的影响,而完全不同的。

convertToNodeSpace、convertToWorldSpace,都是以参照物的左下角作为坐标点原点,向右和向上创建坐标系。
------------------------------convertToNodeSpace,获得的坐标相对于参照物的坐标。
------------------------------convertToWorldSpace,获得的坐标是参照物所在的坐标系中的坐标,即转换到参照物的世界坐标。

convertToNodeSpaceAR、convertToWorldSpaceAR,是以参照物的锚点为原点,向右、向上创建坐标系。
------------------------------convertToNodeSpaceAR,获得的坐标相对于参照物的坐标(此时坐标系的原点在参照物的锚点)。
------------------------------convertToWorldSpaceAR,获得的坐标是参照物所在的坐标系中的坐标,即转换到参照物的世界坐标(此时坐标系的原点在参照物的锚点)。
这样理解比较简单写,有AR的是以参照物的锚点作为新建坐标系的原点,没有AR的是以参照物的左下角作为新建坐标系的原点。

世界坐标一般都是游戏中的场景的绝对坐标,相对坐标是在世界范围内参照其他元素的坐标,绝对坐标,相对坐标,类似于物理中的绝对运动和相对运动

若 A 的绝对坐标是(20, 20),B 的绝对坐标是(30, 40)那么A—>convertToNodeSpace(B->getPosition()) 
指的是计算 B 相对 A 的相对坐标,那就是以 A 为参照计算 B 的新坐标 =(30-20, 40-20)=(10, 20),
反过来 B->convertToNodeSpace(A->getPosition()) 就是以 B 为参照计算
 A = (20-30, 20-40)=(-10, -20)(PS:convertToNodeSpace(A->getPosition()) 中的 A->getPosition() 是绝对坐标)
下面计算世界坐标,计算世界坐标是根据相对坐标进行计算,好好理解这句话
若这个时候 A (30, 40) B (5, 6)都是绝对坐标,但是利用下面这个函数 
A->convertToWorldSpace(B->getPosition())这个时候 B (5, 6)就变成了 A 的相对坐标了,这个时候得到的新坐标(35, 46)
1.convertToNodeSpace
Vec2 newPosition = node1->convertToNodeSpace(node2->getPosition());
将node2的位置坐标转换成相对于node1左下角顶点的坐标。转换方法:node1和node2位置不变,将坐标轴原点设置为node1的左下角顶点,重新计算node2->getPosition()这个点的坐标即为newPosition。
当调用此方法,返回的是相对于其父节点的节点坐标,当然了,以下代码的实际用处并不大。

2.convertToNodeSpaceAR
Vec2 newPosition=node1->convertToNodeSpaceAR(node2->getPosition());
将node2的位置坐标转换成相对于node1锚点的坐标。转换方法:node1和node2位置不变,将坐标轴原点设置为node1的锚点,重新计算node2->getPosition()这个点的坐标即为newPosition。

3.convertToWorldSpace
Vec2 newPosition=node1->convertToWorldSpace(node2->getPosition());
将node2的位置坐标转换成世界坐标。转换方法:node1的位置不变,世界坐标的坐标轴也不变,以node1的左下角顶点再建立一个坐标系(其实就是本地坐标),将node2->getPosition()这个点设置到新建的坐标系中,以原来的世界坐标系为参考,重新计算node2->getPosition()这个点的坐标即为newPosition。

4.convertToWorldSpaceAR
Vec2 newPosition=node1->convertToWorldSpaceAR(node2->getPosition());
将node2的位置坐标转换成世界坐标。转换方法:node1的位置不变,世界坐标的坐标轴也不变,以node1的锚点再建立一个坐标系,将node2->getPosition()这个点设置到新建的坐标系中,以原来的世界坐标系为参考,重新计算node2->getPosition()这个点的坐标即为newPosition。

首先我们添加两个测试精灵(宽:27,高:40)到场景里面:

Sprite *sprite1 = Sprite::create("player.png");
sprite1->setPosition(Vec2(20, 40));
sprite1->setAnchorPoint(Vec2(0, 0));
this->addChild(sprite1);

Sprite *sprite2 = Sprite::create("player.png");
sprite2->setPosition(Vec2(-15, -30));
sprite2->setAnchorPoint(Vec2(1, 1));
this->addChild(sprite2);

然后调试,在场景中大概是下图这样显示(以左下角为坐标原点,从左到右为x方向,从下到上为y方向,废话了:)):
在cocos2d-x中,每个精灵都有一个锚点,以后对精灵的操作(比如旋转)都会围绕锚点进行,我们暂且可以看作是精灵的中心位置,一般来说有每个方向有三种可能的值:0,0.5,1。上图中红色圆点即为各自的锚点,sprite1 锚点为 (0,0) 左下角,sprite2锚点为(1,1)在右上角。
现在我们来看看坐标系转换,同样地,我们先写点测试代码:

Point p1 = sprite2->convertToNodeSpace(sprite1->getPosition());
Point p2 = sprite2->convertToWorldSpace(sprite1->getPosition());
Point p3 = sprite2->convertToNodeSpaceAR(sprite1->getPosition());
Point p4 = sprite2->convertToWorldSpaceAR(sprite1->getPosition());
接着,再打印出各点的x,y值:
Log("p1:%f,%f", p1.x, p1.y);
Log("p2:%f,%f", p2.x, p2.y);
Log("p3:%f,%f", p3.x, p3.y);
Log("p4:%f,%f", p4.x, p4.y);

由于cocos2d-x的坐标系(本地坐标系)是以左下角为坐标原点的,所以 sprite1和sprite2的坐标原点在上图的位置分别是(20,40)、(-42,-70),那么很明显的:

  1. p1就是sprite1锚点相对于sprite2原点来说在sprite2坐标系中的位置,经过对比上图,我们可以得到(20-(-42),40-(-70))即(62,110)
  2. p2就是sprite1锚点相对于sprite2原点来说在上图坐标系中的位置,这样我们可以计算出sprite1在sprite2坐标系中的位置:(20+(-42),40+(-70)),即(-22,-30)
  3. p3就是sprite1锚点相对于sprite2锚点来说在sprite2坐标系中的位置,也就是(20-(-15),40-(-30)),即(35,70)
  4. p4就是sprite1锚点相对于sprite2锚点来说在上图坐标系中的位置,也就是(20+(-15),40+(-30)),即(5,10)
  5. 现在我们可以知道,计算方法都是用sprite1的坐标去加减sprite2的坐标,针对本地坐标系就用减法,针对世界坐标系就用加法。

convertToWorldSpace实现过程

Vec2 Node::convertToWorldSpace(const Vec2& nodePoint) const
{
    Mat4 tmp = getNodeToWorldTransform();
    Vec3 vec3(nodePoint.x, nodePoint.y, 0);
    Vec3 ret;
    tmp.transformPoint(vec3,&ret);
    return Vec2(ret.x, ret.y);
}

Mat4 Node::getNodeToWorldTransform() const
{
    return this->getNodeToParentTransform(nullptr);
}

猜你喜欢

转载自blog.csdn.net/ouyangshima/article/details/82984362
今日推荐