在写容器植物类前,需要对Terrain进行一些小小的更新。这次我是把Terrain中提取出Carrier类,让Terrain塔基和容器类植物都继承自这个类,对于Carrier类,添加的内容很少,只是把Terrain以前的代码移动Carrier中就行了
class Carrier
{
//使用cocos2dx,把SDL改成CC即可
SDL_SYNTHESIZE(TerrainType,m_terrainType,TerrainType);//该地形的类型
SDL_BOOL_SYNTHESIZE(m_bDestroyed,Destroyed);//当前的地形是否被毁坏
SDL_SYNTHESIZE(int,m_nRow,Row);
protected:
Plant*m_pInnerPlant;
public:
Carrier();
~Carrier();
void setInnerPlant(Plant*plant);
Plant*getInnerPlant();
};
对于睡莲和花盆,倒是没什么可说的,只是有一个动画而已
class LilyPad : public Plant,public Carrier
{
public:
LilyPad();
~LilyPad();
static LilyPad*create(const string&plantName);
bool init(const string&plantName);
virtual void updateHook(float dt,float elapsed);
virtual void skillHook();
};
睡莲的初始化函数
bool LilyPad::init(const string&plantName)
{
this->setPlantName(plantName);
//设置正常动画
auto animationName = plantName;
auto animation = AnimationCache::getInstance()->getAnimation(animationName);
//设置贴图
auto firstFrame = animation->getFrames().front()->getSpriteFrame();
m_pSprite = Sprite::createWithSpriteFrame(firstFrame);
auto size = m_pSprite->getContentSize();
//设置位置
m_pSprite->setPosition(Point::ZERO);
m_pSprite->setAnchorPoint(Point::ZERO);
this->setContentSize(size);
this->addChild(m_pSprite);
//设置运行动画
Animate*animate = Animate::create(animation);
this->getSprite()->runAction(animate);
return true;
}
然后更新PlantLayer的makePlant函数,使之能生成睡莲和花盆
else if (name == FLOWERPOT_NAME)
{
plant = m_pPlantFactory->createFlowerPot(name);
}
else if (name == LILYPAD_NAME)
{
plant = m_pPlantFactory->createLilyPad(name);
//对莲叶添加一个上下浮动的效果
MoveBy*move1 = MoveBy::create(1.f,Point(0.f,5.f));
MoveBy*move2 = MoveBy::create(1.f,Point(0.f,-5.f));
auto seq = Sequence::createWithTwoActions(move1,move2);
RepeatForever*repeat = RepeatForever::create(seq);
plant->runAction(repeat);
}
睡莲有一个一直重复的向上向下移动效果
然后在LevelLayer中也添加了几个适用于Carrier的函数
//链式获取最上层的植物
Plant*getTopPlant(Terrain*terrain);
//获取植物相邻的容器
Carrier*getVesselOfPlant(Terrain*terrain,Plant*plant);
//获取植物的tag
int getSumOfTagPlant(Terrain*terrain,Plant*plant);
分别看看实现吧
Plant*LevelLayer::getTopPlant(Terrain*terrain)
{
auto innerPlant = terrain->getInnerPlant();
while (innerPlant != nullptr
&& innerPlant->getPlantType() == PlantType::Vessel)
{
auto vessel = dynamic_cast<Carrier*>(innerPlant);
//容器中还存在植物
if (vessel->getInnerPlant() != nullptr)
{
innerPlant = vessel->getInnerPlant();
}
else
{
break;
}
}
return innerPlant;
}
这个函数是获取的最上层的植物,链式进行获取,如果该植物是容器类植物,则进行动态类型转换,另外,这个不可以使用静态类型转换,因为Carrier和Plant没有关系。
Carrier*LevelLayer::getVesselOfPlant(Terrain*terrain,Plant*plant)
{
auto innerPlant = terrain->getInnerPlant();
while (innerPlant != nullptr
&& innerPlant->getPlantType() == PlantType::Vessel)
{
auto vessel = dynamic_cast<Carrier*>(innerPlant);
//容器中存在对应的植物
if (vessel->getInnerPlant() == plant)
{
return vessel;
}
else
{
innerPlant = vessel->getInnerPlant();
}
}
return terrain;
}
这个函数是获取植物所相邻的容器。
比如水面上种睡莲,则该容器是水面。水面上种睡莲,向日葵,那么向日葵的容器就是睡莲。
{
int tag = 0;
Carrier*carrier = terrain;
do
{
tag += carrier->getRow();
auto innerPlant = carrier->getInnerPlant();
if (plant == innerPlant)
break;
else if (innerPlant->getPlantType() == PlantType::Vessel)
carrier = dynamic_cast<Carrier*>(innerPlant);
else
break;
}while(carrier != nullptr);
return tag;
}
这个是获取植物对应的tag,是为了便于植物之间的显示确定
bool GameScene::tryPlanting(Card*card,Terrain*terrain)
{
auto topPlant = m_pLevelLayer->getTopPlant(terrain);
Plant*newPlant = nullptr;
Point newPos;
//获取必要物品
auto necessaryItem = card->getNecessoryItem();
//升级植物
if (!necessaryItem.empty() && topPlant != nullptr
&& topPlant->getPlantName() == necessaryItem)
{
//获取临近容器
auto vessel = m_pLevelLayer->getVesselOfPlant(terrain,topPlant);
//创建新植物
newPlant = m_pPlantLayer->makePlant(card->getCardName());
newPos = terrain->getPosition();
//该容器为容器类植物
if (vessel != terrain)
{
auto vesselPlant = dynamic_cast<Plant*>(vessel);
auto height = topPlant->getContentSize().height;
auto offsetPos = Point(0.f,-height/2.f);
newPos = vesselPlant->getPosition() + offsetPos;
newPlant->setVesselPlant(vesselPlant);
}
vessel->setInnerPlant(newPlant);
//移除旧植物
m_pPlantLayer->removePlant(topPlant);
topPlant->removeFromParent();
}
//种植植物
else if (necessaryItem.empty())
{
//地形上的植物为空 并且地形符合,则创建
if (topPlant == nullptr && card->isIncludeTerrain(terrain->getTerrainType()))
{
newPlant = m_pPlantLayer->makePlant(card->getCardName());
//再设置一些基础属性
newPos = terrain->getPosition();
terrain->setInnerPlant(newPlant);
if (newPlant->getPlantType() == PlantType::Vessel)
{
dynamic_cast<Carrier*>(newPlant)->setRow(terrain->getRow());
}
}
//存在容器植物,继续判断
else if(topPlant != nullptr && topPlant->getPlantType() == PlantType::Vessel)
{
auto height = topPlant->getContentSize().height;
auto vessel = dynamic_cast<Carrier*>(topPlant);
auto offsetPos = Point(0.f,-height/2.f);
if (card->isIncludeTerrain(vessel->getTerrainType()))
{
newPlant = m_pPlantLayer->makePlant(card->getCardName());
//再设置一些基础属性
newPos = topPlant->getPosition() + offsetPos;
vessel->setInnerPlant(newPlant);
newPlant->setVesselPlant(topPlant);
}
}//end else if
}
//设置基础属性
if (newPlant != nullptr)
{
newPlant->setActiveTime(card->getActiveTime());
newPlant->setPosition(newPos);
newPlant->setDelegate(this);
//添加到entity layer 场景
auto entityLayer = this->getEntityLayer();
int tag = m_pLevelLayer->getSumOfTagPlant(terrain,newPlant);
entityLayer->addChild(newPlant,tag);
}
return newPlant != nullptr;
}
tryPlanting又更新了一次,添加了容器植物的相关逻辑
本节截图