先看看目前僵尸层的实现
class ZombieLayerDelegate
{
public:
virtual Terrain*findTerrainOfZombieCollision(ZombieBase*zombie)=0;
};
class ZombieLayer : public Layer
{
private:
map<int,vector<ZombieBase*> > m_zombies;
//TODO扩展使用
vector<ZombiePath*> m_zombiePaths;
ZombieFactory*m_pZombieFactory;
ZombieLayerDelegate*m_pDelegate;
public:
ZombieLayer();
~ZombieLayer();
CREATE_FUNC(ZombieLayer);
bool init();
virtual void update(float dt);
//生成僵尸
ZombieBase*makeZombie(const string&zombieName,int row);
void setZombiePaths(const vector<ZombiePath*>& paths);
//设置委托
void setDelegate(ZombieLayerDelegate*pDelegate);
};
这里面僵尸存储是以行进行存储的,这样也是为了方便以后植物的攻击
在僵尸层中为僵尸设置目标
void ZombieLayer::update(float dt)
{
for (auto mapIter = m_zombies.begin(); mapIter != m_zombies.end();mapIter++)
{
auto vec = mapIter->second;
for (auto vecIter = vec.begin();vecIter != vec.end();)
{
auto zombie = *vecIter;
//僵尸死亡或者当前已经有目标,则不进行更新
if (zombie->isDying() || zombie->getAim() != nullptr)
{
++vecIter;
}
//当前僵尸已经死亡TODO
else if (zombie->isDead())
{
}
else
{
//获取和僵尸碰撞的塔基
auto terrain = m_pDelegate->findTerrainOfZombieCollision(zombie);
//当前塔基存在植物,设置目标
if (terrain->getInnerPlant() != nullptr)
{
zombie->setAim(terrain);
}
vecIter++;
}
zombie->update(dt);
}
}
}
在僵尸层中为僵尸设置了攻击目标,可以看到,只有塔基上存在植物,才会设置为当前目标
Terrain*GameScene::findTerrainOfZombieCollision(ZombieBase*zombie)
{
//获取当前僵尸所在的行
auto row = zombie->getRow();
auto dir = zombie->getZombieDir();
auto r = zombie->getCollisionBoundingBox();
const auto&terrains = m_pLevelLayer->getTerrainsOfRow(row);
Terrain*terrain = nullptr;
//地形从左向右遍历
if (dir == ZombieDir::Left)
{
for (auto it = terrains.begin();it != terrains.end();it++)
{
auto t = *it;
auto rect = t->getBoundingBox();
if (r.intersectsRect(rect))
{
terrain = t;
break;
}
}
}
//地形从右向左遍历
else if (dir == ZombieDir::Right)
{
//TODO
}
return terrain;
}
这里涉及到一行塔基的遍历问题,目前仅仅考虑从左向右遍历,获取第一个和僵尸发生碰撞的塔基,然后返回。
需要理解GameScene是作为MVC中的C,即控制器,关于MVC,不懂的可以百度。
class GameScene : public Scene
,public TouchLayerDelegate,public LevelLayerDelegate,public PlantDelegate
,public ZombieLayerDelegate,public ZombieDelegate
{
private:
TouchLayer*m_pTouchLayer;
LevelLayer*m_pLevelLayer;
PlantLayer*m_pPlantLayer;
ZombieLayer*m_pZombieLayer;
CardLayer*m_pCardLayer;
PanelLayer*m_pPanelLayer;
ProductLayer*m_pProductLayer;
bool m_bSwallowTouch;
public:
GameScene();
~GameScene();
CREATE_FUNC(GameScene);
bool init();
virtual void update(float dt);
//删除植物
void removePlant(Plant*plant);
private://内部使用
void preloadResources();
//加载关卡回调函数
void levelLoadCallback();
//加载卡片
void loadCard(LevelCardType levelType);
//关卡开始
void levelStart(LevelCardType levelType);
void collectProduct(Product*product);
//尝试创建植物
bool tryPlanting(Card*card,Terrain*terrain);
//尝试创建僵尸
bool tryMakingZombie(Card*card,Terrain*terrain);
private:
//todo
void addSun(int num);
void subSun(int num);
//生成阳光
void makeSun(int number,FiniteTimeAction*action,const Point&bornPos);
TMXLayer* getEntityLayer();
virtual Plant*getTopPlant(Terrain*terrain);
private://delegate
virtual bool onTouchBegan(Touch*,SDL_Event*);
virtual void onTouchMoved(Touch*touch,SDL_Event*event);
virtual void onTouchEnded(Touch*touch,SDL_Event*event);
virtual Terrain*findTerrainOfZombieCollision(ZombieBase*zombie);
};
这个就是目前的Game Scene的方法和成员
本节游戏截图
可以看到,僵尸正在攻击花盆(花盆里的向日葵已经死亡。。。)