[Cocos2d塔防遊戲開發]Cocos2dx-3.X完成塔防遊戲《王國保衛戰》--子彈類(一)

該章節主要介紹防禦塔的子彈

有了防禦塔沒有子彈類是不能攻擊敵人的,所以接着來討論子彈,新建一個子彈基類Bullet.h

class Bullet : public Sprite
{
public:
    Bullet();
    ~Bullet();
    virtual bool init();
    CREATE_FUNC(Bullet);

protected:
    CC_SYNTHESIZE(int, maxForce, MaxForce);//攻擊力
    CC_SYNTHESIZE(int, bulletScope, BulletScope);//塔的子彈攻擊範圍
    CC_SYNTHESIZE(int, bulletType, BulletType);//子彈類型
    CC_SYNTHESIZE(Spawn*, bulletAction, BulletAction);//子彈飛行動畫
    Sprite* sprite;//子彈精靈-貼圖
    virtual void shoot(){};//攻擊
    virtual void removeBullet(){};//攻擊完畢後移除
};

在基類中我們定義了一些共有的方法和屬性,然後根據不同的子彈來重寫它

例如上一篇提到的初級箭塔的弓箭,我們需要重寫init()來給精靈貼上弓箭這張圖片(arrow.png在plist裏,實現加載過該plist,具體加載過程見開始動畫章節)

bool Arrow::init()
{
    if (!Sprite::init())
    {
	return false;
    }
    sprite = Sprite::createWithSpriteFrameName("arrow.png");
    addChild(sprite);		
    return true;
}
然後重寫shoot(),弓箭的攻擊動作最簡單,新建一個動畫序列,先執行箭塔根據自身位置和敵人位置生成的弧線和弓箭自身旋轉的動畫,然後執行removeBullet

void Arrow::shoot()
{
    SoundManager::playArrowRelease();//播放音效
    runAction(Sequence::create(bulletAction,
        CallFuncN::create(CC_CALLBACK_0(Arrow::removeBullet, this)),
        NULL));
}
其中弓箭在執行完上述動畫後,若此時弓箭所在位置與敵人位置重疊即擊中敵人,則根據攻擊力減少敵人血量,弓箭所在的區域如下:

auto bulletRect = Rect(

                                this->getPositionX() +this->getParent()->getPositionX() - this->getContentSize().width /2,

                                this->getPositionY() +this->getParent()->getPositionY() - this->getContentSize().height/2,

this->sprite->getContentSize().width,

                                this->sprite->getContentSize().height );

因爲弓箭是由防禦塔創建並且添加在防禦塔建造點那個精靈上上,所以需要通過this->getParent()->getPositionX() 先來獲取防禦塔X軸所在的位置,this->getPositionX() 即子彈相對於防禦塔的X軸位置,兩者相加即子彈在地圖所在的位置,Y軸同理,根據寬高計算相應的區域。

然後我們遍歷保存在單例中的敵人,若區域重疊,則判斷集中,進行更新敵人血量、執行噴血(血腥~)動畫等動作。

具體思路來自於cocos2dx官網《賊來了》這款教程,但不同的是他將子彈的動畫與擊中敵人等動作由地圖類完成,通過每一幀來判斷是否集中敵人,這樣方案在2D平面中可行,因爲這款遊戲是2.5D的,弓箭有一個飛到最高點並下落的過程,所以必須由其自身執行,並在其動畫結束在判斷。、

若爲集中敵人,有一個弓箭插在地上並且等待若干時間後消失的動畫

void Arrow::removeBullet()
{
	bool isMissed = true;//判斷是否擊中,默認未擊中
        auto instance = GameManager::getInstance();
   
	auto bulletRect = Rect(this->getPositionX() +this->getParent()->getPositionX() - this->getContentSize().width /2,
                                this->getPositionY() +this->getParent()->getPositionY() - this->getContentSize().height/2,
								this->sprite->getContentSize().width,
                                this->sprite->getContentSize().height );
	
	auto monsterVector = instance->monsterVector;
        //遍歷
	for (int j = 0; j < monsterVector.size(); j++)
	{
		auto monster = monsterVector.at(j);
		auto monsterRect = monster->baseSprite->getBoundingBox();
		//判斷是否重疊並且可以被士兵擊中,即不在地下(有種地下的敵人無法被射中)	
		if (monsterRect.intersectsRect(bulletRect) && monster->getAttackBySoldier())
		{
			auto currHp = monster->getCurrHp();

			currHp =  currHp - this->getMaxForce() + monster->getArmor();//
                
			if(currHp <= 0){
				currHp = 0;
			}
			monster->setCurrHp( currHp );

			monster->getHpBar()->setPercentage((currHp/monster->getMaxHp())*100);//更新血條
			monster->getHurt();
                        isMissed = false;  //設爲擊中  
			if(currHp == 0){
				monster->death();
			}
			break;
		}
	}
	if(isMissed){//若未擊中

		sprite->setSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName("decal_arrow.png"));

		sprite->runAction(Sequence::create(FadeOut::create(1.0f)
					,CallFuncN::create(CC_CALLBACK_0(Bullet::removeFromParent, this))
                                       , NULL));
	}else{
		this->removeFromParent();
	}
}

這就是最簡單的子彈類---弓箭,還有其他子彈例如炮彈、導彈甚至震盪波,巫毒圖騰等~也是這個思路,只不過動畫複雜的鞋


有了地圖,防禦塔,子彈,相信初學者已經可以獨立完成這款遊戲了,下面將介紹基本怪物類


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章