微信经典飞机大战之五:触摸事件及其优先级

这节我们将阐述飞机的触摸事件及其优先级。整个游戏的触摸事件处理,放在GameLayer中。

1.CCStandardTouch和CCTargetedTouch

因为GameLayer继承于CCLayer,那么我们先来看一下CCLayer的声明:

class CC_DLL CCLayer : public CCNode, public CCTouchDelegate, public CCAccelerometerDelegate, public CCKeypadDelegate

它继承于CCNode,也是也继承了3个硬件相关接口事件,分别是CCTouchDelegate(触摸事件),CCAccelerometerDelegate(加速器事件)和CCKeypadDelegate(键盘事件)。因此我们可以直接在CCLayer中进行触摸事件的处理。

触摸事件有两个类,CCStandardTouch和CCTargetedTouch。前者为多点触摸,后者为单点触摸,从函数的参数就可以看得出。系统默认注册前者分发事件,我们需要在这里重载registerWithTouchSpatcher,设置为对单点触摸有效。

		//在init函数中设置为可触摸
		this->setTouchEnabled(true);

void GameLayer::registerWithTouchDispatcher()
{
	CCDirector* pDirector=CCDirector::sharedDirector();
	pDirector->getTouchDispatcher()->addTargetedDelegate(this,0,true);
}

2.触摸的回调函数

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);
		}
	}
}

MoveTo函数在PlaneLayer.cpp中

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);
	}
}

3.触摸优先级和触摸事件的吞噬

有一个地方需要注意,addTargetedDelegate第二个和第三个参数,代表什么意思呢?

第二个参数表示触摸事件的优先级,值越小,代表优先级越高。例如层1的优先级是0,层2的优先级是-50,那么层2会先接手并处理触摸事件,然后层1才有机会来接手处理。

第三个参数表示swallow事件,表示当前层是否要吞噬这个触摸事件,即不让优先级更低的层接收。

另外,触摸事件的触发是根据添加的顺序依次触发的,后添加的层先捕获触摸事件。当然,这是在没有设置事件优先级的情况下,若要是定义了事件的优先级,则先按照事件的优先级依次被触发,然后根据添加的顺序依次被触发。


你可能感兴趣的:(优先级,触摸事件,CCTargetedTouch,经典飞机大战,CCStandardTouch)