这节我们将阐述飞机的触摸事件及其优先级。整个游戏的触摸事件处理,放在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.xwinSize.width-planeSize.width/2)
{
location.x=winSize.width-planeSize.width/2;
}
if(location.ywinSize.height-planeSize.height/2)
{
location.y=winSize.height-planeSize.height/2;
}
this->getChildByTag(AIRPLANE)->setPosition(location);
}
}
有一个地方需要注意,addTargetedDelegate第二个和第三个参数,代表什么意思呢?
第二个参数表示触摸事件的优先级,值越小,代表优先级越高。例如层1的优先级是0,层2的优先级是-50,那么层2会先接手并处理触摸事件,然后层1才有机会来接手处理。
第三个参数表示swallow事件,表示当前层是否要吞噬这个触摸事件,即不让优先级更低的层接收。
另外,触摸事件的触发是根据添加的顺序依次触发的,后添加的层先捕获触摸事件。当然,这是在没有设置事件优先级的情况下,若要是定义了事件的优先级,则先按照事件的优先级依次被触发,然后根据添加的顺序依次被触发。