[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();
	}
}





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