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

該章節主要介紹防禦塔的基本性質和製作思路


首先我們定義一個防禦塔的基類BaseTower 

class BaseTower: public Sprite


我們要先確定一個塔所具備的屬性,這些可以根據自己所設計的遊戲需要來自行定義,例如:

   CC_SYNTHESIZE(TowerType, towerType, TowerType); //類型
   CC_SYNTHESIZE(Terrain*, myTerrain, MyTerrain);  //建造點
   CC_SYNTHESIZE(std::string, towerName, TowerName); //名稱
   CC_SYNTHESIZE(int, level, Level);//等級
   CC_SYNTHESIZE(float, scope, Scope);//範圍
   CC_SYNTHESIZE(float, nextScope, NextScope);//升級後範圍
   CC_SYNTHESIZE(float, rate, Rate);//攻擊速度
   CC_SYNTHESIZE(int, force, Force);//攻擊力
   CC_SYNTHESIZE(int, updateMoney, UpdateMoney);//升級所需金錢
   CC_SYNTHESIZE(int, buildMoney, BuildMoney);//售出時返還金錢

然後定義一些可能出現的公共方法,在不同的防禦塔子類中實現:

public:
  virtual void updateTower(){};//升級防禦塔(基礎升級)
  virtual void sellTower();//售賣防禦塔
  virtual void removeTower();//移除防禦塔
  virtual bool init();//初始化防禦塔
  virtual void showTowerInfo();//顯示防禦塔信息
  virtual void update1(){};//兩種升級方向
  virtual void update2(){};
  virtual void setRallyPoint(Point point){};//兵營塔的設置集結點
protected: 
  virtual void checkNearestMonster();//檢測附近敵人
  BaseMonster* nearestMonster;  //附近的敵人
  bool onTouchBegan(Touch *touch, Event *event);
  void onTouchEnded(Touch* touch, Event* event);
  virtual void showUpdateMenu(){};//顯示升級選項
  virtual void hideUpdateMenu();//隱藏
  Sprite* terrain;//該塔的建造點
  void setListener();//設置某些監聽事件
每個防禦塔會有自己的shoot(float dt)之類的方法(根據防禦塔類型不同而不同),通過schedule(schedule_selector(BaseTower::shoot), 0.5f);定時調用,此時的0.5f就和防禦塔的攻擊速率有關,越短,攻擊速度越快。


防禦塔攻擊敵人的思路參考了http://www.cocos.com/doc/tutorial/show?id=1108這篇文章,感謝作者


每次防禦塔執行自己的shoot方法時,首先執行CheckNearestMonster來檢測附近是否存在可以攻擊的敵人


void BaseTower::checkNearestMonster()
{
    auto instance = GameManager::getInstance();
    auto monsterVector = instance->monsterVector;//全局Vector變量,用來存儲當前關卡的敵人
    
    auto currMinDistant = this->scope; 
    
    nearestMonster = NULL;
    for(int i = 0; i < monsterVector.size(); i++)
    {
	auto monster = monsterVector.at(i);
	double distance = this->getParent()->getPosition().getDistance(monster->baseSprite->getPosition());//算座標距離

	if (distance < currMinDistant && monster->getAttackByTower()) { //當在塔的範圍內,且怪物可以被攻擊(某些地下怪物只有鑽出地面可以被攻擊)
	    currMinDistant = distance;//設置最小距離,找到最近的怪物
            <pre name="code" class="cpp">            nearestMonster <span style="font-family: Arial, Helvetica, sans-serif;">= monster</span>
} }}


其中計算距離的時候有個getParent()是因爲每個防禦塔是建造在一個Terrain精靈類上面,這樣的好處是1原版遊戲在建造點建造防禦塔時,可以看到建造點扔在防禦塔下面,2即使防禦塔被賣掉,建造點扔在,不用重新去生成,方便管理(我是這麼設計的...)

然後就是關鍵的shoot方法了,炮塔,弓箭塔,法師塔的原理基本一樣,只是攻擊的動畫和軌跡計算不同而已,只有兵營塔略微不同,這些都將在下一章講解。。。

通過setLinstener()給防禦塔設置觸摸時間

void BaseTower::setListener()
{
  auto listener = EventListenerTouchOneByOne::create();
  listener->onTouchBegan = CC_CALLBACK_2(BaseTower::onTouchBegan, this);
  listener->onTouchEnded = CC_CALLBACK_2(BaseTower::onTouchEnded, this);
  _eventDispatcher->addEventListenerWithSceneGraphPriority(listener,terrain);
}


對觸摸事件進行相應處理:

不攔截Touch
bool BaseTower::onTouchBegan(Touch *touch, Event *event)
{
	return true;
}

void BaseTower::onTouchEnded(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))//當觸摸點在防禦塔內(即點擊防禦塔,目前只能通過此方法來判斷是否點擊防禦塔)
	{  	
	  static_cast<BaseMap*>(this->getParent()->getParent())->playerState->showTowerInfo(getTowerType());//調用父父佈局(BaseMap)的PlayState層,顯示防禦塔信息
	  if(isUpdateMenuShown)//如果防禦塔升級界面已經顯示,則隱藏,某種顯示
	  {
		hideUpdateMenu();
	  }else{
		showUpdateMenu();
	  }
	}else{//觸摸點在外面則隱藏防禦塔升級界面
	  hideUpdateMenu();
	}
}





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