cocos2d-x坐标转换

CONVERT POINT FUNC

cocos2d-x中,Node类有六个坐标转换函数,分别是:

  • Vec2 convertToNodeSpace(const Vec2& worldPoint) const;
  • Vec2 convertToWorldSpace(const Vec2& nodePoint) const;
  • Vec2 convertToNodeSpaceAR(const Vec2& worldPoint) const;
  • Vec2 convertToWorldSpaceAR(const Vec2& nodePoint) const;
  • Vec2 convertTouchToNodeSpace(Touch * touch) const;
  • Vec2 convertTouchToNodeSpaceAR(Touch * touch) const;
    前四个函数作用于将传入的某个坐标转化为当前节点(调用者)的本地坐标系或世界坐标系(也就是父节点/scene的本地坐标系)中。后两个方便在触摸操作时直接转换,效果相同。

convertToWorldSpace:把基于当前节点的本地坐标系下的坐标转换到世界坐标系中。
convertToNodeSpace:把世界坐标转换到当前节点的本地坐标系中。

使用

例如,在飞机大战项目中,宠物是玩家的子节点,玩家是游戏场景的子节点,子弹层是游戏场景的子节点。子弹层计算子弹都在世界坐标系(基于游戏场景的本地坐标系)下。
玩家发射子弹时调用addBullet方法时直接调用getPosition函数就可以获得世界坐标。
如果宠物直接调用getPosition所得到的是自己在父节点的本地坐标系中的位置。这里是(-100,0)。直接传入addBullet将被看做基于游戏场景的本地坐标系,也就是这里的“世界坐标系”,很显然得不到预期结果。此时需要利用convert系列函数进行坐标转换。

void CPet::openFire(float fDelta)
{
	Vec2 vec1 = this->getParent()->getPosition();
	Vec2 vec2 = this->getPosition();
	Vec2 vec = this->getParent()->convertToWorldSpaceAR(vec2); //坐标转换
	CFly::getInstance()->getBulletLayer()->addBullet(vec, m_strBulletName);
}

为什么不是Vec2 vec = this->convertToWorldSpaceAR(vec2);呢?

原因是vec2需要转换到玩家所在的世界坐标,实际上vec2已经是宠物的“世界坐标”了——getPosition得到自己在父节点的本地坐标系中的位置,而父节点的本地坐标系就是子节点的“世界坐标系”。将世界坐标再次转换为世界坐标很明显是一件不符合逻辑的事。

因此,转换的重点是:
convertToWorldSpace:把基于当前节点的本地坐标系下的坐标转换到世界坐标系中。
convertToNodeSpace:把世界坐标转换到当前节点的本地坐标系中。

Vec2 vec = this->getParent()->convertToWorldSpaceAR(vec2); //坐标转换这句的正确理解应该是“找到玩家节点的本地坐标系中宠物的位置,再调用玩家的convertToWorldSpace将其转化到更广阔的世界坐标系(游戏场景的本地坐标系)中。”

基准点

  • convertToWorldSpaceconvertToWorldSpace
    这两种转换都是不考虑锚点的,都以当前节点父类的左下角的坐标为标准。
  • convertToNodeSpaceARconvertToWorldSpaceAR
    注意到这两个方法只不过增加了AR的约束,也即锚点。其意思是:修改变换的基准。这样理解:
    convertToNodeSpaceAR,就是将节点坐标系的坐标原点修改在其锚点位置。(convertToNodeSpace 节点坐标系的原点位置是其左下角 )
    convertToWorldSpaceAR,就是在变换的时候将参照坐标修改到其锚点位置。(convertToWorldSpace 参照坐标是在其左下角 )

参考

Cocos2d-x 详解坐标系统

原文地址:https://www.cnblogs.com/holm/p/13714945.html