游戏人生,混乱的坐标系和锚点
2014-06-08 17:48
288 查看
有关坐标和适配的问题往往让人发指,最近项目对worldtoNode,nodetoworld搞的我头都大了好多圈,加上ancher和适配,笔者都快疯了,这里准备做个系类,把这里的东西屡一下,整理个文档。
先从坐标系和锚点开始。这里想提醒读者,这部分看似简单,其实挺混乱的,而且相当重要。
coco2dx中涉及四种坐标
GL坐标系:
Cocos2D以OpenglES为图形库,所以它使用OpenglES坐标系。GL坐标系原点在屏幕左下角,x轴向右,y轴向上。
屏幕坐标:
系苹果的Quarze2D使用的是不同的坐标系统,原点在屏幕左上角,x轴向右,y轴向下。ios的屏幕触摸事件CCTouch传入的位置信息使用的是该坐标系。因此在cocos2d中对触摸事件做出响应前需要首先把触摸点转化到GL坐标系。可以使用CCDirector的convertToGL来完成这一转化。
世界坐标系:
也叫做绝对坐标系。世界坐标系和GL坐标系一致,原点在屏幕左下角。
本地坐标系:
本地坐标系也叫做物体坐标系,是和特定物体相关联的坐标系(父节点)
其实GL坐标和世界坐标是一样的,屏幕坐标对于使用cocos2dx的开发者而言大部分时间可以无视,那么其实需要大家理解的就是——世界坐标,本地坐标。
本地坐标是相对于父节点而言的坐标,例如在一个CCLayer中添加一个CCSprite,此时setPosition设置的就是相对CCLaye的本地坐标。在渲染的过程中会将本地坐标变成世界坐标,所以我们很难发现其实我们设置的是相对坐标。那么相对坐标究竟是什么坐标?世界坐标是以屏幕坐下角为(0,0),x轴向右,y轴向上的坐标,本地坐标则是以其父节点坐标为(0,0),x轴向右,y轴向上的坐标。带入个场景:
一个Layer里添加一个sprite,设置layer坐标为(100,100),sprite坐标(0,0)
然后放开注释,this->setPosition(ccp(100,100))
相信大家有些理解相对坐标了,在不设置layer坐标的情况下layer坐标(0,0),sprite的setposition(0,0)与世界坐标一样,都是坐下角为原点。但是layer坐标变为(100,100)之后,sprite坐标就变成了父节点layer的坐标(100,100)为原点的相对坐标位置。
cocos2dx在这里提供了2个方法,将世界坐标与本地坐标相对转化,只不过有点坑的是你需要知道世界坐标与父节点的坐标。
CCPoint convertToNodeSpace(const CCPoint& worldPoint);
CCPoint convertToWorldSpace(const CCPoint& nodePoint);
cocos的某系操作基于本地坐标,例如moveTo,有些是基于世界坐标,例如touch。当我们需要touch时间检测碰撞或者触摸,然后移动sprite的时候就需要用到以上函数了。
如果运行以上代码,如果sprite的父节点坐标为(0,0),那么精灵会点击的时候移动到点击位置,如果不是(0,0),那么恭喜你,精灵会移动到想都想不到的地方。怎么解决?我的方法是使用moveBy,计算点击位置与精灵位置的矢量差,通过moveBy移动。
接下来咱们说说锚点:
这是一个难以理解的东西,什么是锚点?这个不好说,还是看看下边的例子吧。
首先ignoreAnchorPointForPosition这个东西,很神奇,先看看设置为false的情况。
pSprite->setAnchorPoint(ccp(0.5,0.5));
在ignoreAnchorPointForPosition(false);的情况下,设置锚点可以这样理解,设置位置就是设置锚点的位置,当锚点为(0,0)的时候,图片的左下角为锚点,图片左下角与设置位置重合。当锚点为(0.5,0.5)时候,图片的中点为锚点,设置位置(0,0)就是图片中点位置为(0,0)。
在说说ignoreAnchorPointForPosition(true)的情况,设置锚点为(0.5,0.5),运行后如下
这是什么情况? 我们先命名一个变量:父子点,父节点提供给子节点的坐标系原点。经过测试,设置为ture之后,设置子节点锚点时父子点一同被设置,父节点的父子点和sprite的锚点都被设置到了中点上,所以当setPosition为(0.5,0.5),sprite位置(0,0)的时候,就是父节点的父子点与sprite的锚点重合,得到如上情况。
总结一下:所谓的设置位置,用的都是本地坐标,设置的是相对位置。设置位置就是设置父子点与子锚点之间的相对位置关系。锚点从0-1,及从左到右,从下到上。默认情况下父子点位置为父节点左下角。默认情况下ignoreAnchorPointForPosition为FALSE,锚点为(0.5,0.5)
先从坐标系和锚点开始。这里想提醒读者,这部分看似简单,其实挺混乱的,而且相当重要。
coco2dx中涉及四种坐标
GL坐标系:
Cocos2D以OpenglES为图形库,所以它使用OpenglES坐标系。GL坐标系原点在屏幕左下角,x轴向右,y轴向上。
屏幕坐标:
系苹果的Quarze2D使用的是不同的坐标系统,原点在屏幕左上角,x轴向右,y轴向下。ios的屏幕触摸事件CCTouch传入的位置信息使用的是该坐标系。因此在cocos2d中对触摸事件做出响应前需要首先把触摸点转化到GL坐标系。可以使用CCDirector的convertToGL来完成这一转化。
世界坐标系:
也叫做绝对坐标系。世界坐标系和GL坐标系一致,原点在屏幕左下角。
本地坐标系:
本地坐标系也叫做物体坐标系,是和特定物体相关联的坐标系(父节点)
其实GL坐标和世界坐标是一样的,屏幕坐标对于使用cocos2dx的开发者而言大部分时间可以无视,那么其实需要大家理解的就是——世界坐标,本地坐标。
本地坐标是相对于父节点而言的坐标,例如在一个CCLayer中添加一个CCSprite,此时setPosition设置的就是相对CCLaye的本地坐标。在渲染的过程中会将本地坐标变成世界坐标,所以我们很难发现其实我们设置的是相对坐标。那么相对坐标究竟是什么坐标?世界坐标是以屏幕坐下角为(0,0),x轴向右,y轴向上的坐标,本地坐标则是以其父节点坐标为(0,0),x轴向右,y轴向上的坐标。带入个场景:
一个Layer里添加一个sprite,设置layer坐标为(100,100),sprite坐标(0,0)
bool HelloWorld::init() { ////////////////////////////// // 1. super init first if ( !CCLayer::init() ) { return false; } <span style="white-space:pre"> </span>//this->setPosition(ccp(100,100)); // add "HelloWorld" splash screen" CCSprite* pSprite = CCSprite::create("HelloWorld.png"); pSprite->setScale(0.5f); pSprite->setPosition(ccp(0,0)); this->addChild(pSprite, 1); return true; }
然后放开注释,this->setPosition(ccp(100,100))
相信大家有些理解相对坐标了,在不设置layer坐标的情况下layer坐标(0,0),sprite的setposition(0,0)与世界坐标一样,都是坐下角为原点。但是layer坐标变为(100,100)之后,sprite坐标就变成了父节点layer的坐标(100,100)为原点的相对坐标位置。
cocos2dx在这里提供了2个方法,将世界坐标与本地坐标相对转化,只不过有点坑的是你需要知道世界坐标与父节点的坐标。
CCPoint convertToNodeSpace(const CCPoint& worldPoint);
CCPoint convertToWorldSpace(const CCPoint& nodePoint);
cocos的某系操作基于本地坐标,例如moveTo,有些是基于世界坐标,例如touch。当我们需要touch时间检测碰撞或者触摸,然后移动sprite的时候就需要用到以上函数了。
CCRect pRect = pSprite->boundingBox(); pRect.origin = pSprite->convertToWorldSpace(ccp(0,0)); if(pRect.containsPoint(ccp(x,y))) { CCLOG("监测到点击精灵事件"); CCActionInterval* anim = CCMoveTo::create(1.0f,ccp(x,y)); pSprite->runAction(anim); }
如果运行以上代码,如果sprite的父节点坐标为(0,0),那么精灵会点击的时候移动到点击位置,如果不是(0,0),那么恭喜你,精灵会移动到想都想不到的地方。怎么解决?我的方法是使用moveBy,计算点击位置与精灵位置的矢量差,通过moveBy移动。
接下来咱们说说锚点:
这是一个难以理解的东西,什么是锚点?这个不好说,还是看看下边的例子吧。
首先ignoreAnchorPointForPosition这个东西,很神奇,先看看设置为false的情况。
bool HelloWorld::init() { ////////////////////////////// // 1. super init first if ( !CCLayer::init() ) { return false; } // add "HelloWorld" splash screen" CCSprite* pSprite = CCSprite::create("HelloWorld.png"); pSprite->setScale(0.5f); pSprite->setPosition(ccp(0,0)); pSprite->ignoreAnchorPointForPosition(false); pSprite->setAnchorPoint(ccp(0,0)); CCPoint point = this->getAnchorPoint(); this->addChild(pSprite, 1); //initScroll(); return true; }
pSprite->setAnchorPoint(ccp(0.5,0.5));
在ignoreAnchorPointForPosition(false);的情况下,设置锚点可以这样理解,设置位置就是设置锚点的位置,当锚点为(0,0)的时候,图片的左下角为锚点,图片左下角与设置位置重合。当锚点为(0.5,0.5)时候,图片的中点为锚点,设置位置(0,0)就是图片中点位置为(0,0)。
在说说ignoreAnchorPointForPosition(true)的情况,设置锚点为(0.5,0.5),运行后如下
这是什么情况? 我们先命名一个变量:父子点,父节点提供给子节点的坐标系原点。经过测试,设置为ture之后,设置子节点锚点时父子点一同被设置,父节点的父子点和sprite的锚点都被设置到了中点上,所以当setPosition为(0.5,0.5),sprite位置(0,0)的时候,就是父节点的父子点与sprite的锚点重合,得到如上情况。
总结一下:所谓的设置位置,用的都是本地坐标,设置的是相对位置。设置位置就是设置父子点与子锚点之间的相对位置关系。锚点从0-1,及从左到右,从下到上。默认情况下父子点位置为父节点左下角。默认情况下ignoreAnchorPointForPosition为FALSE,锚点为(0.5,0.5)
相关文章推荐
- 二、Cocos2dx概念介绍(游戏开发中不同的坐标系,cocos2dx锚点)
- 二、Cocos2dx-游戏开发中不同的坐标系,cocos2dx锚点
- Cocos2dx概念介绍(游戏开发中不同的坐标系,cocos2dx锚点)
- Cocos2dx-游戏开发中不同的坐标系,cocos2dx锚点
- 关于Coco2dx中锚点的问题,游戏坐标系,节点坐标系
- 我,游戏,世界——网瘾少年的二十年游戏人生
- Cocos2d-x 3.0final 终结者系列教程08-绘图节点Node中的锚点和坐标系
- 人生如游戏,容错性很关键
- 人生-游戏
- 0002-游戏人生、生存模式、人生哲学、阶层与模式
- nyoj 1111 游戏人生(区间DP)
- Python之模拟职场人生游戏
- 雷鸣的游戏人生(一) --- 三个笑话
- 游戏人生Silverlight(1) - 七彩俄罗斯方块[Silverlight 2.0(c#)]
- 游戏里的人生-扎克斯
- 3D数学基础 图形与游戏开发的学习 (六)[多坐标系]
- 【项目经理之修炼(7)】《基础篇》人生游戏中的神器——谦虚
- [windows+cocos2dx](绝对/相对)坐标系、锚点、深度、
- 幸福的人生,有好多的"游戏"~~
- convertTouchToNodeSpaceAR转换为精灵锚点所在坐标系