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