[cocos2dx學習筆記]用cocos2dx3.X完成塔防遊戲王國保衛戰--地圖(二),mfccocos2dx3.0

來源:互聯網
上載者:User

[cocos2dx學習筆記]用cocos2dx3.X完成塔防遊戲王國保衛戰--地圖(二),mfccocos2dx3.0

接上文,添加地圖,在地圖層直接添加即可,我是將AnchorPoint設定在(0,0),方便計算座標

mapSprite = Sprite::createWithSpriteFrameName(String::createWithFormat("Stage_%d.png",level+1)->getCString());mapSprite->setAnchorPoint(Point(0,0));mapSprite->setPosition(Point(0,0));addChild(mapSprite);

本章節主要介紹兩個固定技能和商店技能的實現


首先是兩個固定技能,以隕石為例

首先添加按鍵圖片精靈

stoneSprite = Sprite::createWithSpriteFrameName("power_portrait_fireball_0001.png");stoneSprite->setAnchorPoint(Point(0,0));stoneSprite->setPosition(Point(10,-20));stoneSprite->setName("inactive");//判斷倒計時是否完畢completeStone = false;addChild(stoneSprite,1);     

然後是倒計時遮蓋層,採用的是ProgressTimer實現,放在按鍵圖片精靈上面

stoneTimer = ProgressTimer::create(Sprite::createWithSpriteFrameName("power_loading.png"));stoneTimer->setAnchorPoint(Point(0,0));//順時針轉動stoneTimer->setReverseDirection(true);stoneTimer->setPosition(Point(10,-20));stoneTimer->setPercentage(100);//顯示原形的百分比this->addChild(stoneTimer,1);


添加定時器,更新ProgressTimer狀態

void PlayerStateMenu::updateStoneProgress(float Dt){  stoneTimer->setPercentage(stoneTimer->getPercentage() - Dt*2);//更新進度2if (stoneTimer->getPercentage()==0) {this->unschedule(schedule_selector(PlayerStateMenu::updateStoneProgress));//取消定時器completeStone = true;}return;}

在你想要開始的時候schedule它比如第一波敵人出現之後


添加觸摸響應

auto stoneListener = EventListenerTouchOneByOne::create();stoneListener->onTouchBegan = [&](Touch* touch, Event* event){auto target = static_cast<Sprite*>(event->getCurrentTarget());Point locationInNode = target->convertTouchToNodeSpace(touch);Size size = target->getContentSize();Rect rect = Rect(0, 0, size.width, size.height);//若第一次點擊點擊if(rect.containsPoint(locationInNode)){//若冷卻結束if(completeStone == true){//移出其他技能觸摸監聽mTouchLayer->removeAllListener();if(stoneSprite->getName() == "inactive"){//設定為點擊狀態stoneSprite->setSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("power_portrait_fireball_0002.png"));//改變狀態TAGstoneSprite->setName("active");//改變其他2個按鍵狀態/********///觸摸層設定隕石技能監聽mTouchLayer->setFireBallTouchShield();//第二次點擊,即取消}else{mTouchLayer->removeFireBallTouchShield();stoneSprite->setSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("power_portrait_fireball_0001.png"));stoneSprite->setName("inactive");<span style="white-space:pre"></span>}<span style="white-space:pre"></span>}return true;}return false;  };stoneListener->onTouchEnded = [&](Touch* touch, Event* event){};//觸摸吞噬stoneListener->setSwallowTouches(true);_eventDispatcher->addEventListenerWithSceneGraphPriority(stoneListener,stoneSprite);

當倒計時結束的時候,將completeStone置為true,只有此時點擊按鍵才會觸發。

點擊技能,在觸摸層添加一個EventListenerTouchOneByOne,覆蓋整個觸摸層,此時點擊地圖時,會執行這個觸摸事件

下面來看看觸摸層


class TouchLayer :public Layer{public:virtual bool init();    CREATE_FUNC(TouchLayer);EventListenerTouchOneByOne* touchlistener;EventListenerTouchOneByOne* FiereBalllistener;void setFireBallTouchShield();void removeFireBallTouchShield();bool onFireBallTouchBegan(Touch* touch, Event* event);void onFireBallTouchEnded(Touch* touch, Event* event);bool isFlag;bool onTouchBegan(Touch* touch, Event* event);void onTouchEnded(Touch* touch, Event* event);void onTouchMoved(Touch* touch, Event* event);Size winSize;bool isMoved;void removeAllListener();};
這裡我只截取了和隕石有關以及移動地圖的部分


在BaseMap裡添加觸摸監聽層

void BaseMap::initTouchLayer(){mTouchLayer = TouchLayer::create();mTouchLayer->setContentSize(mapSprite->getContentSize());mTouchLayer->setAnchorPoint(Point(0,0));mTouchLayer->setPosition(Point(0,0));addChild(mTouchLayer,99);}

添加地圖移動時間觸摸

touchlistener = EventListenerTouchOneByOne::create();touchlistener->onTouchBegan = CC_CALLBACK_2(TouchLayer::onTouchBegan, this);touchlistener->onTouchEnded = CC_CALLBACK_2(TouchLayer::onTouchEnded, this);touchlistener->onTouchMoved = CC_CALLBACK_2(TouchLayer::onTouchMoved, this);touchlistener->setSwallowTouches(true);_eventDispatcher->addEventListenerWithFixedPriority(touchlistener,-1);_eventDispatcher->addEventListenerWithSceneGraphPriority(touchlistener,this);


這裡設定將FiexPriority設定為-1為了確保觸摸事件先與技能等其他觸摸時間觸發

void TouchLayer::onTouchEnded(Touch* touch, Event* event){<span style="white-space:pre"></span>touchlistener->setSwallowTouches(isMoved);isMoved = false;}void TouchLayer::onTouchMoved(Touch* touch, Event* event){        // 計算滑動過程中的滑動增量        auto diff = touch->getDelta(); //手指移動修正,因為手指觸摸不像滑鼠觸摸那麼固定if(abs(diff.x) >5|| abs(diff.y) >5){isMoved = true;}// 得到當前bgSprite的位置auto currentPos = this->getParent()->getPosition();// 得到滑動後bgSprite應該所在的位置auto pos = currentPos + diff;//邊界控制,約束pos的位置pos.x = MIN(pos.x, 0);pos.x = MAX(pos.x, -1200 + winSize.width);pos.y = MIN(pos.y, 0);pos.y = MAX(pos.y, -1000 + winSize.height);// 重設地圖層位置this->getParent()->setPosition(pos);}

當手指在觸摸層上移動的時候,isMoved會為true,這是setSwallowTouches(isMoved)會將其他觸摸事件吞噬
這樣是為了確保移動的時候經過或者移動結束的時候碰巧在某觸摸點時,不會觸發其他觸摸事件(比如說移動完手指正好在某個防禦塔上,這樣就不會彈出防禦塔升級層)
另外當移動的時候也不會觸發技能事件監聽,可以移動完再選擇技能釋放地點


void TouchLayer::setFireBallTouchShield(){//調用此方法建立隕石技能觸摸時間FiereBalllistener = EventListenerTouchOneByOne::create();FiereBalllistener->onTouchBegan = CC_CALLBACK_2(TouchLayer::onFireBallTouchBegan, this);FiereBalllistener->onTouchEnded = CC_CALLBACK_2(TouchLayer::onFireBallTouchEnded, this);FiereBalllistener->setSwallowTouches(true);//設定比移動觸摸事件高即可_eventDispatcher->addEventListenerWithFixedPriority(FiereBalllistener,1);_eventDispatcher->addEventListenerWithSceneGraphPriority(FiereBalllistener,this);}void TouchLayer::removeFireBallTouchShield(){//使用技能完畢去除此監聽時間if(FiereBalllistener!=NULL)_eventDispatcher->removeEventListener(FiereBalllistener);}bool TouchLayer::onFireBallTouchBegan(Touch* touch, Event* event){//直接返回TRUE,攔截其他時間return true;}void TouchLayer::onFireBallTouchEnded(Touch* touch, Event* event){//播放音效SoundManager::playFireballUnleash();//建立3個隕石auto fireBall1 = FireBall::create();addChild(fireBall1);fireBall1->shoot(static_cast<TouchLayer*>(event->getCurrentTarget())->convertTouchToNodeSpace(touch)+Point(-30,300));auto fireBall2 = FireBall::create();addChild(fireBall2);fireBall2->shoot(static_cast<TouchLayer*>(event->getCurrentTarget())->convertTouchToNodeSpace(touch)+Point(0,350));auto fireBall3 = FireBall::create();addChild(fireBall3);fireBall3->shoot(static_cast<TouchLayer*>(event->getCurrentTarget())->convertTouchToNodeSpace(touch)+Point(30,280));//隕石墜落之後擷取父類的玩家狀態層,調用startStone,重新開始計時並且重設ProgressTimer遮蓋層static_cast<BaseMap*>(this->getParent())->playerState->startStone();//移除此監聽事件removeFireBallTouchShield();}

我實現整個技能監聽加上觸摸移動差不多就是這樣

商店技能,召喚士兵等其他技能也是同樣的思路,只是使用的技能不同罷了~其他的例如冰凍敵人、召喚士兵等將在對應的模組中一一介紹


今天先暫時寫到這樣,還有苦逼的實習等著我去找






聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.