1.节点与子节点的坐标系之间的关系
1.1简要介绍各种坐标系:
2. 屏幕坐标系:原点在屏幕左上角,x轴向右,y轴向下。
因此在Cocos2D-X中对触摸事件做出响应前,需要首先把触摸点转化到OpenGL坐标系。
3. 节点坐标系:每个节点都有独立的坐标系。当节点移动或者改变方向时,和该节点相关联的坐标系(它的子节点坐标系)将随之移动或者改变方向。都是相对的,相对于基准的。
1.2父子节点坐标系之间的关系:
CCNode类的设置位置使用的是父节点的节点坐标系。它和OpenGL坐标系的方向也是一致的,x轴向右,y轴向上,原点在父节点坐标系的左下角
如果将父节点的锚点设置为(0.5,0.5),则其子节点的坐标原点在屏幕中央。 (感谢舍予天涯提出错误)。
现纠正错误如下:
锚点为指定贴图上和所在节点原点(即在父节点所形成的坐标系中设置位置的点)重合的点的位置,与贴图上点所比较的并非父节点的左下角,应该说是贴图所在节点的左下角(即子节点本身的原点)。
综合来说,锚点是贴图上的某一点,与父节点坐标系并无关系,而仅仅是相对于贴图本身所在节点在父坐标系中的位置(即子节点的原点)。
只有在使用贴图的情况下,锚点才有意义。
CCNode类的默认锚点为(0,0),即节点的左下角。而CCSprite类的默认锚点为(0.5,0.5)。
2.单点触摸
2.1基本步骤
2.2实例:父节点中的某个子节点随手指移动
//触屏检测
setTouchEnabled(true);
isControl = false;
...
//新建父节点
anode = CCNode::create();
anode->setAnchorPoint(ccp(0.5, 0.5));
anode->setPosition(ccp(winSize.width/2, winSize.height/2));
this->addChild(anode, 0);
//新建子节点pSprite
pSprite = CCSprite::create("HelloWorld.png");
pSprite->setScale(0.5);
// position the sprite on the center of the screen
//pSprite和hero作为anode的子节点,所以基于anode的坐标系,以anode的锚点为原点
pSprite->setPosition(ccp(0, 0));
//新建子节点hero
hero = CCSprite::create("r2.png");
hero->setPosition(ccp(0, 0));
//节点缩放比例
nodeScale = 1;
anode->addChild(pSprite, 0);
anode->addChild(hero, 0);
//是否多点触屏
isMultiPoint = false;
void HelloWorld::registerWithTouchDispatcher(){
CCDirector* pDirector = CCDirector::sharedDirector();
//单点触摸
pDirector->getTouchDispatcher()->addTargetedDelegate(this, 0, false);
//多点触摸
pDirector->getTouchDispatcher()->addStandardDelegate(this, 0);
}
//单点触摸
bool HelloWorld::ccTouchBegan(CCTouch* touch, CCEvent* event)
{
CCPoint heropos = hero->getPosition();
//获得触摸点在屏幕坐标系下的坐标
CCPoint location = touch->getLocationInView();
//将其转化为OpenGl坐标
location = CCDirector::sharedDirector()->convertToGL(location);
//再对应到anode节点自己的坐标系
location = anode->convertTouchToNodeSpace(touch);
//锚点似乎在中心哦
CCRect heroRect = CCRectMake(heropos.x - (hero->getContentSize().width/2), heropos.y - (hero->getContentSize().height/2), hero->getContentSize().width, hero->getContentSize().height);
if (nodeScale != 1)
{
heroRect.setRect(heropos.x - ((hero->getContentSize().width) * nodeScale / 2), heropos.y - ((hero->getContentSize().height) * nodeScale / 2), (hero->getContentSize().width) * nodeScale, (hero->getContentSize().height) * nodeScale);
}
//1.首先在ccTouchBegan函数中判断触摸点是否在主角的图片矩形范围内,若在这个范围内,则将布尔型的全局变量设置为true
if (heroRect.containsPoint(location))
{
isControl = true;
CCLOG("yes");
}
return true;
}
void HelloWorld::ccTouchMoved(CCTouch* touch, CCEvent* event)
{
//在ccTouchMoved中,若布尔型的全局变量为true,说明在ccTouchBegan中触点已经控制主角,并根据触摸点的横纵坐标设置主角位置
if (isControl)
{
CCPoint location = touch->getLocationInView();
location = CCDirector::sharedDirector()->convertToGL(location);
location = anode->convertTouchToNodeSpace(touch);
hero->setPosition(ccp(location.x, location.y));
}
}
//3.在ccTouchEnded和ccTouchCancelled中,将布尔型全局变量设置为false即可
void HelloWorld::ccTouchEnded(CCTouch* touch, CCEvent* event)
{
isControl = false;
}
void HelloWorld::ccTouchCancelled(CCTouch* touch, CCEvent* event)
{
isControl = false;
}
6.详细代码见 http://download.youkuaiyun.com/detail/yupingliu/6267063.
3.多点触摸
3.1基本步骤
3.2实例:缩放功能的实现
//多点触摸
void HelloWorld::ccTouchesBegan(CCSet* pTouches, CCEvent* pEvent)
{
//在ccTouchesBegan中检测,如果触摸点的个数大于两个,那么取前两个点,使用两点间距离公式(横纵坐标差的平方和开根号)计算这两个点的距离
if (pTouches->count() >= 2)
{
CCSetIterator iter = pTouches->begin();
CCPoint mPoint1 = ((CCTouch*)(*iter))->getLocationInView();
mPoint1 = CCDirector::sharedDirector()->convertToGL(mPoint1);
iter ++;
CCPoint mPoint2 = ((CCTouch*)(*iter))->getLocationInView();
mPoint2 = CCDirector::sharedDirector()->convertToGL(mPoint2);
distance = sqrt((mPoint1.x - mPoint2.x) * (mPoint1.x - mPoint2.x) + (mPoint1.y - mPoint2.y) * (mPoint1.y - mPoint2.y));
}
}
//多点触摸
void HelloWorld::ccTouchesBegan(CCSet* pTouches, CCEvent* pEvent)
{
//在ccTouchesBegan中检测,如果触摸点的个数大于两个,那么取前两个点,使用两点间距离公式(横纵坐标差的平方和开根号)计算这两个点的距离
if (pTouches->count() >= 2)
{
CCSetIterator iter = pTouches->begin();
CCPoint mPoint1 = ((CCTouch*)(*iter))->getLocationInView();
mPoint1 = CCDirector::sharedDirector()->convertToGL(mPoint1);
iter ++;
CCPoint mPoint2 = ((CCTouch*)(*iter))->getLocationInView();
mPoint2 = CCDirector::sharedDirector()->convertToGL(mPoint2);
distance = sqrt((mPoint1.x - mPoint2.x) * (mPoint1.x - mPoint2.x) + (mPoint1.y - mPoint2.y) * (mPoint1.y - mPoint2.y));
}
}
void HelloWorld::ccTouchesMoved(CCSet* pTouches, CCEvent* pEvent)
{
//在ccTouchesMoved中检测,如果触摸点的个数大于两个,那么继续计算这两个点的距离
if (pTouches->count() >=2)
{
CCSetIterator iter = pTouches->begin();
CCPoint mPoint1 = ((CCTouch*)(*iter))->getLocationInView();
mPoint1 = CCDirector::sharedDirector()->convertToGL(mPoint1);
iter ++;
CCPoint mPoint2 = ((CCTouch*)(*iter))->getLocationInView();
mPoint2 = CCDirector::sharedDirector()->convertToGL(mPoint2);
float mDistance = sqrt((mPoint1.x - mPoint2.x) * (mPoint1.x - mPoint2.x) + (mPoint1.y - mPoint2.y) * (mPoint1.y - mPoint2.y));
CCLOG("distance = %f", distance);
CCLOG("mDistance = %f", mDistance);
//然后通过距离比计算得到缩放比例
mScale = mDistance / distance;
CCLOG("mScale = %f", mScale);
distance = mDistance;
isMultiPoint = true;
}
}
本文不详尽或错误之处,请各位不吝言辞,多多指教~谢谢~
作者:Louise http://blog.youkuaiyun.com/yupingliu