坐标系

Cocos2d 中 分有大致4个坐标系

1. World space coordinate 世界坐标系
2. Opengl es coordinate Op 坐标系
 
世界坐标系和 Opengl es 坐标系 是 一样的  , 都是以x y( 0, 0) 原地在屏幕的 左下角 , x 轴 朝上, y轴朝右 主要照顾游戏时候 经常为 横屏 使用。
关于世界坐标系转换的 理解 我在stackoverflow 老外这么解释的
convertToWorldSpace: method converts one node space to parent node space ... until it gets to world space.
转换坐标系 到 世界坐标系的方法是 转换一个节点的坐标系到它的父节点坐标系 直到世界坐标系 就是屏幕的坐标系。
那么可以理解为converToWorldSpace 这个方法就是把节点的坐标系转换到父节点的坐标系
Cocos2d <wbr>坐标系 <wbr>浅析

 
下面用2个精灵图片, 图片直接取自cocos2d 自带的图片 一个 72*72 一个 50*50
然后把 小的精灵 插入到 大的精灵的 坐标系中
 

player1 = [CCSprite spriteWithFile:@"Icon-72.png" rect:CGRectMake(0072,72)];

player1.position = ccp(winWidth/2, winHeight/2);

[self addChild:player1 z:0];

player2 = [CCSprite spriteWithFile:@"Icon-Small-50.png" rect:CGRectMake(00,5050)];

[player1 addChild:player2 z:0];

然后得到触摸的点的 本地Node space 坐标系
 

CGPoint touchLocation = [touch locationInView:touch.view];

touchLocation = [[CCDirector sharedDirectorconvertToGL:touchLocation];

touchLocation = [player1 convertToNodeSpace:touchLocation];

Cocos2d <wbr>坐标系 <wbr>浅析

可以看到 点击 72*72图片的时候坐标是 13,12 那就说明 坐标系的原点是在 图片的 左下角 而不是 屏幕的 左下角, 说明我们现在是在 local Node space coordinate 中。
 
那么现在转换到世界坐标系中呢? 或者转换到父级 坐标系 就是 opengl es coordinate 中
 
添加以下代码
 

 CCSprite *player = (CCSprite*)[self getChildByTag:77];

 touchLocation = [player1 convertToWorldSpace:touchLocation];

 NSLog(@"%f, %f", touchLocation.x, touchLocation.y);

然后点击图片后得到的坐标是 223,122

这就说明现在所在的坐标系是world space 或者说 opengl es 坐标系中 也就是 图片的 父级坐标系

Cocos2d <wbr>坐标系 <wbr>浅析

 
3. Node space coordinate 坐标系
 
Node space coordinate 是本地坐标系 也就是 图片或者精灵本身的坐标系 一般都是 以图片左下角 为原点(0,0)
4. UIkit coordinate uikit 坐标系
 
这是 ios view 的坐标系 和 opengl es 坐标系不同的是 这个坐标系 是以 左上角 为 原点 x 轴 向右 , y 轴向下 延生, 主要是大多数 应用 除了 游戏之外 用户都是习惯竖着 拿 设备。
 
Cocos2d <wbr>坐标系 <wbr>浅析

 
 一般来说 我们得到的 触摸点的  坐标都是 UIKit 坐标系的 所以一般在触摸方法比如 cctouchbegan 中
首先把 UIKit 坐标转化成 opengl es 的 

 CGPoint touchLocation = [touch locationInView:touch.view];

 touchLocation = [[CCDirector sharedDirectorconvertToGL:touchLocation];

如果直接想得到 用户是否点击到 精灵 或者图片上面的 本地坐标

再添加这条

touchLocation = [player1 convertToNodeSpace:touchLocation];

当然 用 一条代码 可以代替上面的 2条 省事的话

touchLocation = [player1 convertTouchToNodeSpace: touch];

 ——————————————————————————————————————————————————

// converting local node coordinates to world space
-(CGPoint) convertToWorldSpace:(CGPoint)nodePoint;
-(CGPoint) convertToWorldSpaceAR:(CGPoint)nodePoint;
 
// converting world coordinates to local node space
-(CGPoint) convertToNodeSpace:(CGPoint)worldPoint;
-(CGPoint) convertToNodeSpaceAR:(CGPoint)worldPoint;
 
// converting touch (world) coordinates to local node space
-(CGPoint) convertTouchToNodeSpace:(UITouch*)touch;
-(CGPoint) convertTouchToNodeSpaceAR:(UITouch*)touch;

发现convertToGL 是 CCDirector 类的方法 返回 CGPoint
 
[[CCDirector sharedDirector] convertToGL: CGPoint]
 
先大体放在这
 
为什么要进行 坐标系 之间的转换 可以看看 老外这么说的
A common case is the node's boundingBox.origin point, which is in local node coordinates. You may need to convert this boundingBox.origin to another node's local coordinate space in order to test for collision between nodes, or you may want to convert it to world coordinate space in order to perform collision tests with a bunch of nodes at once.

一般的情况 节点的 boundingBox 原点 在本地的节点坐标系当中。 那么你也许需要把这个节点的 boundingBox 原点 转换到另外一个 节点的本地坐标系当中 来判断 2个 节点是不是碰撞了。或者把这个节点的 boundingBox 转换到 世界坐标系当中来测试一个节点和一群节点的碰撞。

现在来试试第一种情况 把 一个节点 加入到 另外一个节点的坐标系当中
 
// convert a world point to node coordinate space
CGPoint localPoint = [someNode convertToNodeSpace:worldPoint];

现在 我用player1 和 player2 , 把player2 的坐标系 换成 player1 的 再判断点击是不是在坐标系内
touchLocation = [player2 convertToNodeSpace:player1.position];

if(CGRectContainsPoint([player2 textureRect], touchLocation)) {

NSLog(@"Inside");

}else {

NSLog(@"Outside");

}

Cocos2d <wbr>坐标系 <wbr>浅析-2 <wbr>坐标转换

可以看到 player2 的 图片位于靠近原点的位置 但是它的坐标系已经转换为player1 的 local Node space coordinate。

然后点击控制台得到
Cocos2d <wbr>坐标系 <wbr>浅析-2 <wbr>坐标转换
可以看到 不管你怎么点都是 215, 135 的坐标 应为 player1的position 坐标 位于 player2 的本地节点坐标系(Local Node space coordinate)当中, 原点是 player2 的 原点 而不是屏幕左下角的原点
 
先在把player1 移动位置放到 player2 上面 看看 发生什么
 
Cocos2d <wbr>坐标系 <wbr>浅析-2 <wbr>坐标转换
再点击player1 和 player2 控制台输出

Cocos2d <wbr>坐标系 <wbr>浅析-2 <wbr>坐标转换

可以看到 坐标原点已经改变了 

下面给出了几个常用的坐标系转换的情况
把本地坐标系转换为世界坐标系(父)
// convert a local node point to world coordinate space
CGPoint worldPoint = [someNode convertToWorldSpace:localPoint];
本地坐标系相对另外一个坐标系锚点的偏移量, 这个还不太清楚 等会研究
// same as above, but localPoint is offset to be relative to anchorPoint of someNode
CGPoint worldPointAR = [someNode convertToWorldSpaceAR:localPoint];
本地坐标系转换到另外一个节点的坐标系当中(这里是父坐标系)
// convert a local node point to another node's coordinate space
CGPoint targetNodeLocalPoint = [targetNode convertToWorldSpace:otherNodeLocalPoint];
 和上面一样只不过变成了锚地的偏移量
// same as above, but otherNodeLocalPoint is offset to be relative to anchorPoint of targetNode
CGPoint targetNodeLocalPointAR = [targetNode convertToWorldSpaceAR:otherNodeLocalPoint];
 
接下来研究下什么是描点之间坐标系的转换 Anchor relative coordinate conversion

Normally (and unfortunately) cocos2d places child nodes relative to the parent's lower left contentSize corner. In the case of a sprite using a 100x100 image, and the sprite positioned at 400x300, a child node with a position of 0x0 will be centered on the coordinate 400-(100/2)x300-(100/2) = 350x250. This is odd but that's the way cocos2d works. The non-AR conversion coordinates convert coordinates relative to this origin point 350x250 whereas the AR variants convert coordinates relative to the node's anchorPoint, in this case relative to 400x300.

一般或者不幸的是 cocos2d 放置 子节点的位置 是相对 父节点的 左下角的位置这样的方式。 在这个例子里 使用100*100的图片, 精灵位置是 400,300, 一个子节点的位置是 0,0 应该是位于400-100/2 = 350,和300-100/2 = 250中心的地方. 这比较奇怪, 但这就是cocos2d 的方式。(按照一般思维 应该在原点 就是 400, 300 的地方 但是 父节点的锚点不是 0.5 , 0.5 而是 0,0)

The difference between non-AR and AR coordinate conversion methods is merely the distance between the node's lower left origin point and the anchorPointInPoints property. Should the anchorPoint of the node and all of its parents be set to 0x0 (not recommended btw) then both coordinate conversion methods would give you the same results.

这样锚地和 无锚点的坐标系之间转换 将出现很微小的误差, 应该把节点的锚点和所有它的父节点都设置为0,0 ,你将得到正确的结果.

最后是 UIKit coordinate 转换  UIKit coordinate conversion
CGPoint cocosPoint = [[CCDirector sharedDirector] convertToGL:uikitPoint];
CGPoint uikitPoint = [[CCDirector sharedDirector] convertToUI:cocosPoint];
 
但是节点本地坐标系转换到UIkit 坐标系 如下
CGPoint cocosPoint = [someNode convertToWorldSpace:localPoint];
CGPoint uikitPoint = [[CCDirector sharedDirector] convertToUI:cocosPoint];

反之

CGPoint cocosPoint = [[CCDirector sharedDirector] convertToGL:uikitPoint];
CGPoint localPoint = [someNode convertToNodeSpace:cocosPoint];

 

原文地址:https://www.cnblogs.com/bigben0123/p/3723778.html