这节我们将阐述飞机的触摸事件及其优先级。整个游戏的触摸事件处理,放在GameLayer中。
1.CCStandardTouch和CCTargetedTouch
因为GameLayer继承于CCLayer,那么我们先来看一下CCLayer的声明:
class CC_DLL CCLayer : public CCNode, public CCTouchDelegate, public CCAccelerometerDelegate, public CCKeypadDelegate
触摸事件有两个类,CCStandardTouch和CCTargetedTouch。前者为多点触摸,后者为单点触摸,从函数的参数就可以看得出。系统默认注册前者分发事件,我们需要在这里重载registerWithTouchSpatcher,设置为对单点触摸有效。
//在init函数中设置为可触摸 this->setTouchEnabled(true);
void GameLayer::registerWithTouchDispatcher() { CCDirector* pDirector=CCDirector::sharedDirector(); pDirector->getTouchDispatcher()->addTargetedDelegate(this,0,true); }
CCStandardTouch中有四个函数:
virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);//触摸开始调用 virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);//触摸移动调用 virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);//触摸结束调用 virtual void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent);//一般是系统级调用,比如触摸过程中突然来电之类的这里我们只需用到前两个即可。
其中需要注意的是:ccTouchBegan返回的是bool值。
如果返回的是true,表示当前层接受触摸事件,后面的ccTouchMoved, ccTouchEnded和ccTouchCancelled才能调用。
如果返回的是false,表示当前层不接受触摸事件,后面的三个函数也不会被调用。
我们主要在ccTouchMoved中处理飞机移动处理。
bool GameLayer::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent) { return true; //表示当前层接收触摸事件处理 } void GameLayer::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent) { if(this->planeLayer->isAlive) { CCPoint beginPoint=pTouch->getLocationInView(); beginPoint=CCDirector::sharedDirector()->convertToGL(beginPoint); //获取触摸坐标 CCRect planeRect=this->planeLayer->getChildByTag(AIRPLANE)->boundingBox(); //获取飞机当前位置形状位置 planeRect.origin.x-=15; planeRect.origin.y-=15; planeRect.size.width+=30; planeRect.size.height+=30; //允许稍微加大一点触摸位置,游戏实际需要 if(planeRect.containsPoint(this->getParent()->convertTouchToNodeSpace(pTouch))) //判断触摸点是否在飞机范围内 { CCPoint endPoint=pTouch->getPreviousLocationInView(); //获取触目的前一个位置 endPoint=CCDirector::sharedDirector()->convertToGL(endPoint); CCPoint offSet=ccpSub(beginPoint,endPoint); //获取offset CCPoint toPoint=ccpAdd(this->planeLayer->getChildByTag(AIRPLANE)->getPosition(),offSet); //获取真正位移位置 this->planeLayer->MoveTo(toPoint); } } }
void PlaneLayer::MoveTo(CCPoint location) { //飞机及游戏状态判断 if(isAlive && !CCDirector::sharedDirector()->isPaused()) { //进行边界判断,不可超出屏幕 CCPoint actualPoint; CCSize winSize=CCDirector::sharedDirector()->getWinSize(); CCSize planeSize=this->getChildByTag(AIRPLANE)->getContentSize(); if(location.x<planeSize.width/2) { location.x=planeSize.width/2; } if(location.x>winSize.width-planeSize.width/2) { location.x=winSize.width-planeSize.width/2; } if(location.y<planeSize.height/2) { location.y=planeSize.height/2; } if(location.y>winSize.height-planeSize.height/2) { location.y=winSize.height-planeSize.height/2; } this->getChildByTag(AIRPLANE)->setPosition(location); } }
有一个地方需要注意,addTargetedDelegate第二个和第三个参数,代表什么意思呢?
第二个参数表示触摸事件的优先级,值越小,代表优先级越高。例如层1的优先级是0,层2的优先级是-50,那么层2会先接手并处理触摸事件,然后层1才有机会来接手处理。
第三个参数表示swallow事件,表示当前层是否要吞噬这个触摸事件,即不让优先级更低的层接收。
另外,触摸事件的触发是根据添加的顺序依次触发的,后添加的层先捕获触摸事件。当然,这是在没有设置事件优先级的情况下,若要是定义了事件的优先级,则先按照事件的优先级依次被触发,然后根据添加的顺序依次被触发。