飛機也登場了,子彈也可以正常發(fā)射了,但是不能動的飛機算神馬回事,坑爹呢?。?!
整個游戲的觸摸事件處理我們把它放在GameLayer中,比較直觀。
我們先看一下CCLayer的聲明:
class CC_DLL CCLayer : public CCNode, public CCTouchDelegate, public CCAccelerometerDelegate, public CCKeypadDelegate
它是從CCNode繼承來的,同時也繼承了3個硬件相關(guān)接口事件,分別是觸摸事件,加速器事件和鍵盤事件。
所以我們可以直接在CCLayer中進行觸摸事件的處理。
觸摸事件中有兩個類,CCStandradTouch,CCTargetedTouch。前者為多點觸摸,后者為單點觸摸,而系統(tǒng)默認注冊前者分發(fā)事件,我們這里要進行繼續(xù)重載虛函數(shù)registerWithTouchSpatcher,對單點有效。
//init()中設置可觸摸
this->setTouchEnabled(true);
void GameLayer::registerWithTouchDispatcher()
{
CCDirector *pDirector=CCDirector::sharedDirector();
pDirector->getTouchDispatcher()->addTargetedDelegate(this,0,true);
}
CCStandradTouch這里就不進行討論了。
virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);//觸摸開始調(diào)用
virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);//觸摸移動調(diào)用
virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);//觸摸結(jié)束調(diào)用
virtual void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent);//一般是系統(tǒng)級調(diào)用,比如觸摸過程中來電之類的
這里我們只要重寫前兩個就夠了。
其中ccTouchBegan返回的是bool值。
A.如果返回true,表示當前層接收觸摸事件,同時允許ccTouchMoved,ccTouchEnded和ccTouchCancelled的調(diào)用。
B.如果返回false,表示當前層不接受觸摸事件,后面的ccTouchMoved等等也就不往下走了。
而ccTouchMoved就是我們進行飛機移動處理的主戰(zhàn)場了。
//GameLayer.cpp
bool GameLayer::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
{
return true;//表示當前層接收觸摸事件處理
}
void GameLayer::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent)
{
if (this->planeLayer->isAlive)//isAlive是AirPlane的一個成員屬性,表示飛機是否還活著
{
CCPoint beginPoint=pTouch->locationInView();
beginPoint=CCDirector::sharedDirector()->convertToGL(beginPoint); //獲取觸摸坐標
//juggle the area of drag
CCRect planeRect=this->planeLayer->getChildByTag(AIRPLANE)->boundingBox();//獲取飛機當前位置形狀位置
planeRect.origin.x-=15;
planeRect.origin.y-=15;
planeRect.size.width+=30;
planeRect.size.height+=30;//允許稍微加大一點觸摸位置,游戲?qū)嶋H需要
if(CCRect::CCRectContainsPoint(planeRect,
this->getParent()->convertTouchToNodeSpace(pTouch))==true) //判斷觸摸點是否在飛機范圍內(nèi)
{
CCPoint endPoint=pTouch->previousLocationInView();//獲取觸摸的前一個位置
endPoint=CCDirector::sharedDirector()->convertToGL(endPoint);
CCPoint offSet =ccpSub(beginPoint,endPoint);//獲取offset
CCPoint toPoint=ccpAdd(this->planeLayer->getChildByTag(AIRPLANE)->getPosition(),offSet); //獲取真正移動位置
this->planeLayer->MoveTo(toPoint); //移動飛機
}
}
}
//PlaneLayer.cpp
void PlaneLayer::MoveTo(CCPoint location)
{
//飛機及游戲狀態(tài)判斷
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);
}
}
大家看到觸摸事件的分派注冊中,addTargetdDelegate第二個和第三個函參,又是什么意思呢?
A.第二個參數(shù)表示觸摸事件的優(yōu)先級,值越小,優(yōu)先級越高,比如層1的優(yōu)先級是-50,層2的優(yōu)先級是-100,那么層2會先接收并處理觸摸事件,然后才有機會輪到層1來接收處理。
B.第三個參數(shù)表示swallow事件,表示當前層是否吞噬掉這個觸摸,即不往優(yōu)先級更低的層傳送。
要注意的是觸摸事件的觸發(fā)是根據(jù)添加的順序依次觸發(fā)的,后添加的層先捕獲觸摸事件,當然,這是沒有設置事件優(yōu)先級的情況下,若要是定義了事件的優(yōu)先級,則先按照事件的優(yōu)先級依次被觸發(fā),然后根據(jù)添加的順序依次被觸發(fā)。CCMenu的優(yōu)先級是-128,而CCControlButton的優(yōu)先級是0。
好了,這一節(jié)后,我們就可以控制飛機移動并且發(fā)射子彈了,而子彈一旦超出屏幕就會被回收,飛機也不會超出屏幕外。
效果圖
更多建議: